home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gigarom 1
/
Gigarom Macintosh Archives (Quantum Leap)(CDRM1080320)(1993).iso
/
FILES
/
QUI
/
UTI
/
Feature Flick v 1.5.sea
/
CQuickTime.c
< prev
next >
Wrap
Text File
|
1992-10-21
|
113KB
|
4,278 lines
/******************************************************************
"CQuickTime.c"
by: Apple Inc.,
as distributed on their "QuickTime" CD ROM disk
converted to "C" & OOP by: John A. Love, III
using Symantec's "THINK C", v 5.0.2
******************************************************************/
#include <Global.h>
#include <Balloons.h>
#include <Commands.h>
#include <Constants.h>
#include <Files.h>
#include <GestaltEqu.h>
#include <OSChecks.h>
#include <Packages.h>
#include <StandardFile.h>
#include <TCLUtilities.h>
#include <Traps.h>
#include <CBartender.h>
#include <CButton.h>
#include <CClipboard.h>
#include <CDecorator.h>
#include <CDLOGDialog.h>
#include <CFWDesktop.h>
#include <CIntegerText.h>
#include <CList.h>
#include "CmyMisc.h"
#include "CQuickTime.h" // includes "Movies.h"
extern CApplication *gApplication;
extern CBartender *gBartender;
extern CBureaucrat *gGopher;
extern CClipboard *gClipboard;
extern CDecorator *gDecorator;
extern CDesktop *gDesktop;
extern short gClicks;
extern RgnHandle gUtilRgn;
extern OSType gSignature;
extern CursHandle gWatchCursor;
extern CCrsrHandle niftyCameraCRSR;
extern short movieAppRes;
Boolean ShiftKeyIsDownToSelectWholeMovie, FramesPreSelected,
justActivated = false, // For my CView::DispatchCursor…
justSaved = false;
CIconHandle lightOn;
void CMovieDesktop::IMovieDesktop (CBureaucrat *aSupervisor) {
inherited::IFWDesktop(aSupervisor);
} /* IMovieDesktop */
// OVERRIDE
void CMovieDesktop::DispatchCursor (Point where, RgnHandle mouseRgn) {
UseResFile(movieAppRes); // See comments within CMovieApp::StartUpAction
inherited::DispatchCursor (where, mouseRgn);
} /* DispatchCursor */
// OVERRIDE
void CMovieClip::DeactivateWind (CWindow *theWindow) {
/* CClipboard::Toggle hides the clipboard window. Otherwise, we
** could alter the contents of the actual Clipboard and would have
** no easy way to make the clipboard window's contents change while
** it was percolating in the background. By hiding the clipboard
** window, we are forced to select "Show Clipboard" from the Edit
** Menu upon which the clipboard window's contents are updated.
**
** Additionally, Toggle() toggles the Menu Item's text. Also note
** that we do NOT override CDirector::ActivateWind. Activate an
** invisible window -- get a life !!! */
Toggle();
} /* DeactivateWind */
void CMovieDLOGDir::IMovieDLOGDir (short dlogID) {
inherited::IDLOGDirector(dlogID, gApplication);
} /* IMovieDLOGDir */
// OVERRIDE
void CMovieDLOGDir::DoKeyDown (char theChar, Byte keyCode,
EventRecord *macEvent) {
CButton *selectAllBtn;
if (macEvent->modifiers & cmdKey)
{
if (theChar == 'a' || theChar == 'A')
{
selectAllBtn = ((CDialog*) itsWindow)->FindButton(cmdSelectAll);
if (selectAllBtn) selectAllBtn->SimulateClick();
;
DoCommand(cmdSelectAll);
}
else
{
inherited::DoKeyDown(theChar, keyCode, macEvent);
}
}
else inherited::DoKeyDown(theChar, keyCode, macEvent);
} /* DoKeyDown */
// OVERRIDE
void CMovieDLOGDir::DoCommand (long aCmd) {
switch (aCmd)
{
case cmdOK:
EndDialog(cmdOK, TRUE);
/* Don't close Dialog here because eventually DoModalDialog
** will call CButton::SimulateClick and there won't be a
** Button CView around since the window will not exist. */
break;
case cmdCancel:
SysBeep(10);
EndDialog(cmdCancel, FALSE);
break;
case cmdSelectAll:
EndDialog(cmdSelectAll, FALSE);
break;
default:
inherited::DoCommand(aCmd);
break;
}
} /* DoCommand */
void CQuickTime::INoQuickTime (short DLOGid, CApplication *itsSupervisor) {
CDLOGDialog *forShame = NULL;
inherited::IDocument(itsSupervisor, false /* NOT printable */);
forShame = new (CDLOGDialog);
itsWindow = forShame;
forShame->IDLOGDialog(DLOGid, gDesktop, this);
} /* INoQuickTime */
void CQuickTime::DisplayNoQuickTime (void) {
long finalTicks;
Rect windR;
/* System 7 WIND resource automatically centers.
** Howsomever, IDLOGDialog calls AddDITLItems which
** then calls IPicture for a picture Item. Somewhere
** amongst this chain, the above centering is undone: */
// if ( !WINDResourceHasSystem7Field(itsWindow) ) {
short saveProcID = itsWindow->procID;
itsWindow->SetModal(false);
// Gotta do this kludge because CenterWindow tests isModal
// AND the window's procID:
itsWindow->procID = 0;
gDecorator->CenterWindow(itsWindow);
itsWindow->procID = saveProcID;
// }
itsWindow->Select();
itsWindow->Prepare();
itsWindow->Update();
;
SysBeep(10);
SysBeep(10);
;
Delay(60, &finalTicks);
windR = itsWindow->macPort->portRect;
InvertRect(&windR);
Delay(30, &finalTicks);
InvertRect(&windR);
Delay(180, &finalTicks);
} /* DisplayNoQuickTime */
void CQuickTime::IQuickTime (CApplication *itsSupervisor) {
CWindow *theWindow = NULL;
CMovie *theMovie = NULL;
Rect forStarters = {0, 0, 150, 150};
inherited::IDocument(itsSupervisor, false /* NOT printable */);
theWindow = new (CWindow);
itsWindow = theWindow;
/* Un-titled window for now. After we're finished here,
** we will call OpenMovie(...) which will set the window's
** title to the name of the Movie: */
itsWindow->INewWindow(&forStarters, false /* NOT visible */,
noGrowDocProc, false /* NOT floating */,
true /* HAS goAway box */, gDesktop, this);
;
/* CWindow::IWindowX sets minimum window size =
** CWindow::sizeRect.topLeft = {100, 100}. The
** reason for the below value of 1 is that the
** size of an empty Movie = {1, 1, 1, 1}. The
** minimum value = 112 was empirically determined. */
itsWindow->sizeRect.top = 1;
itsWindow->sizeRect.left = 112;
theMovie = new (CMovie);
theMovie ->IMovie(itsWindow, this);
;
itsMovie = theMovie;
itsMainPane = itsMovie;
itsGopher = itsMovie;
savedMovie = nil;
/* For some reason, if my Help Balloon is showing
** it will disappear and will NOT re-appear: */
CView::cCurrHelpView = NULL;
CView::cLastHelpView = NULL;
} /* IQuickTime */
void CQuickTime::INewQuickTime (CApplication *itsSupervisor) {
CWindow *theWindow = NULL;
CMovie *theMovie = NULL;
Rect forStarters = {0, 0, 150, 150};
short numWindows, saveProcID;
Str255 Untitled = "\pUntitled", numString, newTitle;
inherited::IDocument(itsSupervisor, false /* NOT printable */);
theWindow = new (CWindow);
itsWindow = theWindow;
// Un-titled window for now. Below we set title based on window count:
itsWindow->INewWindow(&forStarters, false /* NOT visible */,
noGrowDocProc, false /* NOT floating */,
true /* HAS goAway box */, gDesktop, this);
;
/* CWindow::IWindowX sets minimum window size =
** CWindow::sizeRect.topLeft = {100, 100}. The
** reason for the below value of 1 is that the
** size of an empty Movie = {1, 1, 1, 1}. The
** minimum value = 112 was empirically determined. */
itsWindow->sizeRect.top = 1;
itsWindow->sizeRect.left = 112;
theMovie = new (CMovie);
theMovie ->IMovie(itsWindow, this);
;
itsMovie = theMovie;
itsMainPane = itsMovie;
itsGopher = itsMovie;
savedMovie = nil;
/* Window title is used as part of new file's FSSpec record that
** is created within DoSave. In this manner, CDocument's
** ConfirmClosing method places the window's new title in the
** displayed ALeRT if you try to close the window or quit the
** application without saving any changes to the Movie. */
numWindows = ++(gDecorator->wCount);
NumToString(numWindows, numString);
CopyPString(Untitled, newTitle);
ConcatPStrings(newTitle, "\p - ");
ConcatPStrings(newTitle, numString);
itsWindow->SetTitle(newTitle);
// Make the empty Movie look like a Movie:
itsMovie->NeewMovie(); // Calls NeewController() to do just that.
CView::cCurrHelpView = NULL;
CView::cLastHelpView = NULL;
/* We'll center the window for now ... however, when we later paste
** a Movie, we'll temporarily hide it so we can invisibly re-size
** the window and THEN re-show it. After re-showing, the window's
** topLeft corner retains the value it had after it's centered below: */
saveProcID = itsWindow->procID;
itsWindow->SetModal(false);
itsWindow->procID = 0;
gDecorator->CenterWindow(itsWindow);
itsWindow->procID = saveProcID;
} /* INewQuickTime */
void CQuickTime::DisplayQuickTime (void) {
itsWindow->Select();
itsWindow->Prepare();
} /* DisplayQuickTime */
void CQuickTime::ClearQuickTime (void) {
itsMovie->DisposMoovie(); /* Sets moov = nil. */
itsMovie->DisposController(); /* Sets mc = nil. */
if (savedMovie != nil) /* for reverting */ {
if (GetMovieDuration(savedMovie) > 0) {
DisposeMovie(savedMovie);
FailOSErr( GetMoviesError() );
}
savedMovie = nil;
}
} /* ClearQuickTime */
// OVERRIDE
void CQuickTime::Dispose (void) {
if (itsMovie != NULL) ClearQuickTime();
/* Close Document & window it supervises AFTER we close all the
** above because CDocument::Dispose sets all views and sub-views
** to NULL and "itsMovie" is one of these. CDocument::Dispose
** also dumps CDocument::lastTask, the CTask instance variable
** used for undoing. It also disposes of my CMovieFile since
** I placed it in CDocument::itsFile when I either called
** DoSaveAs with a new Movie or opened an existing Movie file. */
inherited::Dispose();
} /* Dispose */
// OVERRIDE
void CQuickTime::UpdateMenus (void) {
Movie localMoov;
/* Call CDocument::UpdateMenus which enables cmdSaveAs
** and, if CDocument::dirty is TRUE, enables cmdSave.
** Because I am using the identical Command Numbers in
** cmdSaveAsMovie and cmdSaveMovie, respectively, I need
** to carefully re-disable some of these commands depending ... */
inherited::UpdateMenus(); // Keep on trucking !!!
if (itsMovie) {
// gBartender->EnableCmd(cmdCloseMovie); -- done by CDirector::UpdateMenus
localMoov = itsMovie->GetMovie();
/*
** A brand new window is not dirty, so there's nothing to save.
** A cut or cleared window IS dirty even though the resultant
** NeewMovie is empty with a duration = 0. I don't know why
** you'd wish to save an empty Movie, but it can be loaded.
** ... so ...
*/
if (localMoov /* && GetMovieDuration(localMoov) > 0 */) {
/* Done by CDocument's UpdateMenus if (dirty):
** gBartender->EnableCmd(cmdSaveMovie); */
gBartender->EnableCmd(cmdSaveAsMovie);
}
else {
gBartender->DisableCmd(cmdSaveMovie);
gBartender->DisableCmd(cmdSaveAsMovie);
}
} /* itsMovie */
else {
/*
** Gotta be able to close the darn window. If itsMovie = NULL,
** my CQuickTime::Dispose will NOT call ClearQuickTime.
**
** gBartender->DisableCmd(cmdCloseMovie);
*/
gBartender->DisableCmd(cmdSaveMovie);
gBartender->DisableCmd(cmdSaveAsMovie);
}
} /* UpdateMenus */
// OVERRIDE
void CQuickTime::DoCommand (long theCommand) {
if (itsMovie) {
switch (theCommand) {
/* Standard Command Numbers handled by CDocument::DoCommand(...)
case cmdCloseMovie:
this->Close(FALSE); // Calls Dispose.
break;
case cmdSaveMovie:
SetCursor(*gWatchCursor);
DoSave();
break;
case cmdSaveAsMovie:
DoSaveFileAs(); // Calls DoSaveAs.
break;
case cmdRevert:
PositionDialog('ALRT', ALRTrevert);
if (CautionAlert(ALRTrevert, NULL) == OK) {
SetCursor(*gWatchCursor);
DoRevert();
}
break;
case cmdUndo:
if (lastTask != NULL) {
if (undone) lastTask->Redo();
else lastTask->Undo();
undone = !undone;
UpdateUndo();
}
break;
*/
default:
CView::cCurrHelpView = NULL;
CView::cLastHelpView = NULL;
;
inherited::DoCommand(theCommand);
break;
} /* end: switch */
} /* itsMovie */
/*
** Do NOT pass up to CDocument::DoCommand if itsMovie = NULL:
** else inherited::DoCommand(theCommand);
*/
} /* DoCommand */
// OVERRIDE
Boolean CQuickTime::DoSave (void) {
MovieController localMC;
Movie localMoov;
CMovieFile *movieFile = GetMovieFile();
TimeValue currentTime, currentDuration, lengthMovie;
if ( movieFile == NULL /* a brand NeewMovie */ )
return ( DoSaveFileAs() );
else {
/* we came from DoSaveAs OR we created a file when we opened a Movie */
movieFile->Update(); // Calls FlushVol.
/*
** If we came here via DoSaveAs, we called:
** dirty = !dirty;
** so we need to switch back to maintain constancy.
** If we came here via selecting the "Save Movie"
** item under the File MENU, the document was dirty
** to begin with, so we set dirty = false:
*/
dirty = !dirty;
justSaved = true; // For my special CView::DispatchCursor.
// For reverting:
if (savedMovie != nil && GetMovieDuration(savedMovie) > 0) {
DisposeMovie(savedMovie);
FailOSErr( GetMoviesError() );
}
localMC = itsMovie->GetController();
localMoov = itsMovie->GetMovie();
lengthMovie = GetMovieDuration(localMoov);
FailOSErr( GetMoviesError() );
if (lengthMovie > 0) {
GetMovieSelection(localMoov, ¤tTime, ¤tDuration);
FailOSErr( GetMoviesError() );
SetMovieSelection(localMoov, 0 /* beginning */, lengthMovie);
FailOSErr( GetMoviesError() );
localMoov = MCCopy(localMC);
FailOSErr( GetMoviesError() );
SetMovieSelection(localMoov, currentTime, currentDuration);
FailOSErr( GetMoviesError() );
}
else localMoov = NewMovie(newMovieActive);
savedMovie = localMoov;
return (TRUE);
} /* else */
} /* DoSave */
// OVERRIDE
Boolean CQuickTime::DoSaveAs (SFReply *macSFReply) {
CMovieFile *movieFile = GetMovieFile();
StandardFileReply newReply;
short fileRefNum;
Movie newMoov = itsMovie->GetMovie();
WindowPtr localWindow = itsWindow->GetMacPort();
if (movieFile != NULL /* Did NOT come from DoSave */ )
movieFile->Dispose(); // Calls Close().
ConvertOldToNew(macSFReply, &newReply); // Calls FSMakeFSSpec
;
NewFile();
movieFile = GetMovieFile();
movieFile->SpecifyFSSpec(&newReply.sfFile);
movieFile->CreateNew(gSignature, gApplication->sfFileTypes[0]);
movieFile->Open(fsRdWrPerm);
fileRefNum = itsMovie->GetMoovRefNum();
SetMovieActive(newMoov, true);
FailOSErr( GetMoviesError() );
SetMovieGWorld(newMoov, (CGrafPtr) localWindow, nil);
FailOSErr( GetMoviesError() );
MakeFilePreview(fileRefNum, 0);
FailOSErr( GetMoviesError() );
// itsMovie->moov = newMoov; -- knew this coming in.
itsWindow->SetTitle(macSFReply->fName);
dirty = !dirty; // See comments at end of DoSave().
return ( DoSave() );
} /* DoSaveAs */
/*
** OVERRIDE
**
** just to blink on/off the prompt string item when the Movie is empty
**
** CQuickTime::PickFileName
*/
static pascal short MyDlgHook (short theItem, DialogPtr theDialog) {
short promptItem = 3, itemType;
Rect promptBox;
Handle item;
long finalTicks;
if (theItem == sfHookNullEvent /* = 100 */) {
GetDItem(theDialog, promptItem, &itemType, &item, &promptBox);
InvertRect(&promptBox);
Delay(30, &finalTicks);
}
return (theItem);
} /* MyDlgHook */
// OVERRIDE
void CQuickTime::PickFileName (SFReply *macSFReply) {
Point corner; /* Top left corner of dialog box */
Str255 origName, /* Default name for file */
prompt, /* Prompt strings: */
emptyMoviePrompt = "\pWARNING: Movie is EMPTY !!!",
fullMoviePrompt = "\pSave Movie File as:";
Movie localMoov = itsMovie->GetMovie();
Boolean movieIsEmpty = GetMovieDuration(localMoov) == 0,
wasLocked;
ProcPtr filterProc = NULL,
dlgHook = (movieIsEmpty) ? (ProcPtr) &MyDlgHook : NULL;
wasLocked = Lock(TRUE);
FindDlogPosition('DLOG', putDlgID, &corner); // Center Dialog.
GetName(origName);
if (movieIsEmpty) {
CopyPString(emptyMoviePrompt, prompt);
SysBeep(10);
}
else CopyPString(fullMoviePrompt, prompt);
SFPPutFile(corner, prompt, origName, dlgHook, macSFReply, putDlgID, filterProc);
Lock(wasLocked);
} /* PickFileName */
/*
** OVERRIDE
**
** just to implement CMD-key equivalents for responses
**
** CQuickTime::ConfirmClose
*/
static pascal Boolean MyResponseFilter(DialogPtr theDialog,
EventRecord *theEvent,
short *itemHit) {
#define kCR 13
Boolean cmdKeyDown = (theEvent->modifiers & cmdKey) > 0,
processNormally = false,
interceptEvent = true;
char theKey = theEvent->message & charCodeMask;
short itemType;
Rect itemBox;
Handle item;
long finalTicks;
if (theEvent->what != keyDown) return (processNormally);
if (theKey == kEnterKey || theKey == kCR) {
GetDItem(theDialog, *itemHit = answerYES, &itemType, &item, &itemBox);
HiliteControl((ControlHandle)item, inButton);
Delay(20, &finalTicks);
}
else if (cmdKeyDown) {
if (theKey == 'y' || theKey == 'Y') {
GetDItem(theDialog, *itemHit = answerYES, &itemType, &item, &itemBox);
HiliteControl((ControlHandle)item, inButton);
Delay(20, &finalTicks);
}
else if (theKey == 'n' || theKey == 'N') {
GetDItem(theDialog, *itemHit = answerNO, &itemType, &item, &itemBox);
HiliteControl((ControlHandle)item, inButton);
Delay(20, &finalTicks);
}
else if (theKey == '.') {
GetDItem(theDialog, *itemHit = answerCANCEL, &itemType, &item, &itemBox);
HiliteControl((ControlHandle)item, inButton);
Delay(20, &finalTicks);
}
else
return (processNormally);
} /* CMD-key is down */
return (interceptEvent);
} /* MyResponseFilter */
// OVERRIDE
Boolean CQuickTime::ConfirmClose (Boolean quitting) {
Boolean okToClose = TRUE;
Str255 docName, status;
short response;
if (dirty) { /* If Document has changed ... */
if (itsWindow != NULL) itsWindow->Update();
GetName(docName);
GetIndString(status,
STRcommon,
(quitting) ? strQUITTING : strCLOSING);
/* Ask user if s/he wants to save the changes: */
ParamText(docName, status, NULL, NULL);
PositionDialog('ALRT', ALRTsaveChanges);
InitCursor();
response = Alert(ALRTsaveChanges, (ProcPtr) &MyResponseFilter);
if (response == answerYES) {
SetCursor(*gWatchCursor);
okToClose = DoSave(); /* Save Document before closing it. */
}
else if (response == answerCANCEL) {
okToClose = FALSE; /* Abort the close. */
}
/* else if (response == answerNO) we don't need to do
** anything more because "okToClose" was preset to TRUE. */
} /* if dirty */
return(okToClose);
} /* ConfirmClose */
void CQuickTime::NewFile (void) {
CMovieFile *movieFile = NULL;
movieFile = new (CMovieFile);
movieFile->IMovieFile();
SetMovieFile(movieFile); // itsFile = movieFile, etc.
} /* NewFile */
void CQuickTime::OpenMoovFile (SFReply *macSFReply) {
/* Get a movie file and a movie out of the good SFReply: */
StandardFileReply newReply;
Movie localMoov;
OSErr err;
short movieFileRefNum,
rsrcID = 0 /* Get first 'moov' found */;
Boolean wasChanged;
Str255 moovResName;
CMovieFile *movieFile;
ConvertOldToNew(macSFReply, &newReply);
NewFile();
movieFile = GetMovieFile();
movieFile->SpecifyFSSpec(&newReply.sfFile);
movieFile->Open(fsRdWrPerm);
movieFileRefNum = movieFile->refNum; // CResFile::refNum
err = NewMovieFromFile(&localMoov, movieFileRefNum, &rsrcID, moovResName,
newMovieActive, &wasChanged);
if (err == noErr) {
itsMovie->moov = localMoov;
movieFile->resID = rsrcID;
}
else {
movieFile->Dispose(); // Close & Dispose
FailOSErr(err);
}
itsWindow->SetTitle(newReply.sfFile.name);
} /* OpenMoovFile */
void CQuickTime::SetMovieFile (CMovieFile *movieFile) {
movieFile->theMovie = itsMovie;
itsFile = movieFile;
} /* SetMovieFile */
CMovieFile *CQuickTime::GetMovieFile (void) {
return ( (CMovieFile*)itsFile );
} /* GetMovieFile */
void CQuickTime::DoRevert (void) {
/* Close current Movie file without writing-to-disk
** and read in the last saved version of the Movie: */
CMovieFile *movieFile = GetMovieFile();
CMovieEditTask *editTask;
MovieController activeMC;
Movie savedMoov = savedMovie, activeMoov;
TimeValue atStart = 0,
noDuration = 0, movieLength;
GrafPtr currentPort = itsMainPane->GetMacPort();
ASSERT( /*
** CDocument::UpdateMenus won't enable the
** Revert MENU item if CDocument::itsFile = NULL:
**
** movieFile != NULL &&
*/
movieFile->IsOpen()
);
itsWindow->HideSuspend();
;
itsMovie->MakeMovieEditTask(cmdRevert);
activeMC = itsMovie->GetController();
activeMoov = itsMovie->GetMovie();
movieLength = GetMovieDuration(activeMoov);
if (movieLength > 0) {
SetMovieSelection(activeMoov, 0, movieLength);
FailOSErr( GetMoviesError() );
itsMovie->ClearSelection();
}
if (savedMoov != NULL && GetMovieDuration(savedMoov) > 0) {
MCPaste(activeMC, savedMoov);
FailOSErr( GetMoviesError() );
SetMovieSelection(activeMoov, atStart, noDuration); // Zip.
FailOSErr( GetMoviesError() );
GoToBeginningOfMovie(activeMoov);
FailOSErr( GetMoviesError() );
}
Notify(itsMovie->lastMovieEditTask);
itsMovie->lastMovieEditTask->Do();
dirty = false;
;
itsWindow->ShowResume();
} /* DoRevert */
void CMovie::IMovie (CView *anEnclosure, CBureaucrat *aSupervisor) {
inherited::IPane(
anEnclosure, aSupervisor,
0, 0, 0, 0, /* Call FitToEnclosure next */
sizELASTIC, sizELASTIC
);
FitToEnclosure(true, true);
moov = NULL;
mc = NULL;
lastMovieEditTask = NULL;
/* Upon start-up, IApplication sets "gGopher" to my application.
** CBureaucrat::BecomeGopher below resets "gGopher" to this Movie
** view. When CSitchboard::DispatchEvent responds to a click in
** the MenuBar or to a CMD-keypress, eventually the TCL will call
** gGopher->DoCommand(...). Therefore, CMovie::DoCommand is called.
**
** CBureaucrat's BecomeGopher will then call:
** BroadcastChange( bureaucratIsGopher, 0);
** which then calls:
** itsSupervisor->ProviderChanged(this, reason, info);
** where "this" = THIS CMovie view because it was the CBureaucrat
** that was sent the ORIGINAL message = BecomeGopher. Since
** "itsSupervisor" is my document = CQuickTime,
** CDirector::ProviderChanged
** is the contraption that is really called because a CDocument
** is a CDirector.
**
** CDirector's ProviderChanged tests to see if the "this" CMovie
** is active and it's NOT because the enclosing window has not YET
** been activated. As a direct result, "CDirector::itsGopher"
** is NOT changed to my CMovie view. I have to do that when I
** return to either IQuickTime or INewQuickTime.
**
** If I do NOT, look out !!!
**
** Okay ... what have we got so far??? "gGopher" is my CMovie view.
** Before I called IMovie within either IQuickTime or INewQuickTime,
** I called IDocument which called IDirector. IDirector calls:
** itsGopher = this;
** where "this" is my CQuickTime document. Folks, we've got a mismatch.
**
** The purpose of "itsGopher" is to "remember" which bureaucrat is
** supposed to become the gopher when the director's window is made
** active. After I'm completely finished with either IQuickTime or
** INewQuickTime, CWindow::Select is called within DisplayQuickTime
** to finally activate the window. CDirector::ActivateWind gets
** called to set all views and sub-views active. The latter method
** calls CDirector::Activate which, in turn, calls:
** itsGopher->BecomeGopher(TRUE);
**
** WHOOAH !!!!
**
** If we did NOT change "itsGopher" to match "gGopher", then sending
** BecomeGopher to "itsGopher" changes "gGopher" back to "itsGopher"
** which is my CQuickTime document because that's what "itsGopher"
** becomes upon window activation without my intercession (see above
** comments about IDirector). In short, the TCL forces a match. */
BecomeGopher(true);
SetWantsClicks(true); /* IView sets both to false. */
SetCanBeGopher(true);
} /* IMovie */
void CMovie::NeewMovie (void) {
/* Note that we do NOT call CQuickTime's MakeMovieFile
** so that CQuickTime::DoSave can jump over to DoSaveAs
** to create a new FSSpec. */
Movie localMoov;
WindowPtr localWindow = GetMacPort();
Prepare(); // Set the blasted Port !!!
localMoov = NewMovie(newMovieActive); // duration = 0.
moov = localMoov;
SetMovieGWorld(localMoov, (CGrafPtr) localWindow, nil);
FailOSErr( GetMoviesError() );
NeewController();
} /* NeewMovie */
static void FloatingWindow_Update (CWindow *theWindow) {
/* gDesktop->UpdateWindows() called by CMovie::OpenMovie below
** addresses ONLY the CList = CDesktop->itsWindows, NOT the
** CList = ((CFWDesktop*) gDesktop)->itsFloats. So ... */
WindowPeek macWindow;
macWindow = (WindowPeek) theWindow->GetMacPort();
if ( !EmptyRgn(macWindow->updateRgn) ) theWindow->Update();
} /* FloatingWindow_Update */
void CMovie::OpenMovie (SFReply *macSFReply) {
CQuickTime *myDoc = (CQuickTime*) GetSupervisor();
CWindow *theWindow = GetWindow();
WindowPtr localWindow = GetMacPort();
MovieController localMC;
Movie localMoov;
TimeValue atBeginning = 0, currentTime,
currentDuration, lengthMovie;
short saveProcID;
/* We just selected a Movie. The special Movie version of the SFGetFile
** Dialog has just disappeared ... so Update what's there before we play
** the next Movie. Note that if we had NOT selected a Movie by clicking
** the Dialog's <Cancel> Button, CApplication::DoCommand will NOT call
** CStarterApp::OpenDocument to access OpenMovie. However, we WILL
** eventually update all windows the next time through the Event Loop.
** So we only force an immediate update IF we do select a Movie. */
gDesktop->UpdateWindows();
((CMovieDesktop*) gDesktop)->itsFloats->
DoForEach((EachFunc) FloatingWindow_Update);
myDoc->OpenMoovFile(macSFReply);
localMoov = GetMovie();
Prepare();
SetMovieGWorld(localMoov, (CGrafPtr) localWindow, nil);
FailOSErr( GetMoviesError() );
SetMovieActive(localMoov, true);
FailOSErr( GetMoviesError() );
OpenController();
localMC = GetController();
lengthMovie = GetMovieDuration(localMoov);
FailOSErr( GetMoviesError() );
if (lengthMovie > 0) {
GetMovieSelection(localMoov, ¤tTime, ¤tDuration);
FailOSErr( GetMoviesError() );
SetMovieSelection(localMoov, atBeginning, lengthMovie);
FailOSErr( GetMoviesError() );
localMoov = MCCopy(localMC);
FailOSErr( GetMoviesError() );
SetMovieSelection(localMoov, currentTime, currentDuration);
FailOSErr( GetMoviesError() );
}
else localMoov = NewMovie(newMovieActive);
myDoc->savedMovie = localMoov;
PrepCombinedMovieAndController();
/* PrepCombinedMovieAndController will re-size the
** window to accomodate the Movie. Therefore, we
** must wait to center the window until last: */
saveProcID = theWindow->procID;
theWindow->SetModal(false);
theWindow->procID = 0;
gDecorator->CenterWindow(theWindow);
theWindow->procID = saveProcID;
gDecorator->wCount++;
} /* OpenMovie */
Movie CMovie::GetMovie (void) {
return (moov);
} /* GetMovie */
void CMovie::NeewController (void) {
Boolean savedAlloc;
Movie localMoov = GetMovie();
MovieController localMC;
LongRect frameRect = frame;
Rect windRect;
Prepare();
FrameToWindR(&frameRect, &windRect);
savedAlloc = SetAllocation(kAllocCanFail);
localMC = NewMovieController(localMoov, &windRect,
mcTopLeftMovie
/* + mcWithBadge [see ShowBadge below] */);
SetAllocation(savedAlloc);
FailOSErr( GetMoviesError() );
mc = localMC;
SetUpFilter(true);
ShowBadge(true);
EnableKeys(true);
MCEnableEditing(localMC, true);
FailOSErr( GetMoviesError() );
PrepCombinedMovieAndController();
} /* NeewController */
void CMovie::OpenController (void) {
Movie localMoov = GetMovie();
MovieController localMC;
WindowPtr localWindow = GetMacPort();
Point topLeftCorner = {0, 0};
ComponentDescription cd;
Component c, searchAll = nil;
cd.componentType = 'play';
cd.componentSubType = 0; /* none */
cd.componentManufacturer = 'appl';
cd.componentFlags = 0; /* no Register message */
cd.componentFlagsMask = 0; /* ... because componentFlags = 0 */
c = FindNextComponent(searchAll, &cd);
FailNIL(c);
localMC = OpenComponent(c);
FailNIL(localMC);
mc = localMC; /* Stuff into instance variable. */
MCSetControllerAttached(localMC, true);
FailOSErr( GetMoviesError() );
MCSetMovie(localMC, localMoov, localWindow, topLeftCorner);
FailOSErr( GetMoviesError() );
MCSetVisible(localMC, true);
FailOSErr( GetMoviesError() );
MCEnableEditing(localMC, true);
FailOSErr( GetMoviesError() );
SetUpFilter(true);
ShowBadge(true);
EnableKeys(true);
} /* OpenController */
MovieController CMovie::GetController (void) {
return (mc);
} /* GetController */
short CMovie::GetMoovRefNum (void) {
CQuickTime *myDoc = (CQuickTime*) GetSupervisor();
CMovieFile *movieFile = myDoc->GetMovieFile();
if (movieFile) return (movieFile->refNum);
else return (noMoovFile);
} /* GetMoovRefNum */
void CMovie::PrepCombinedMovieAndController (void) {
Movie localMoov = GetMovie();
MovieController localMC = GetController();
CWindow *theWindow = GetWindow();
OSErr err;
Rect moovBox, controllerBox, both, minMaxWindowBounds;
GetMovieBox(localMoov, &moovBox);
FailOSErr( GetMoviesError() );
// Movie box may come with negative coordinates, so ...
OffsetRect(&moovBox, -moovBox.left, -moovBox.top);
SetMovieBox(localMoov, &moovBox);
FailOSErr( GetMoviesError() );
FailOSErr( MCMovieChanged(localMC, localMoov) );
/* CQuickTime::DisplayQuickTime calls CWindow::Select which
** results in an update event which, in turn, results in
** CMovie::Draw being called. The latter calls UpdateMovie:
UpdateMovie(localMoov);
FailOSErr( GetMoviesError() ); */
/* Incorporate a SizeBox as part of the Controller and
** set limits on window growth. The latter is directly
** analogous to setting CWindow::sizeRect to the same limits: */
minMaxWindowBounds = theWindow->sizeRect;
MCDoAction(localMC, mcActionSetGrowBoxBounds, &minMaxWindowBounds);
/* Next get the union of the Controller & Movie boxes in order to size the
** window. You may not have noticed, but the window is NOT growable as far
** as the Window Manager is concerned. When we call MCDoAction below, what
** we are really doing is sending a mcActionControllerSizeChanged action
** message to my MCFilter. This MCFilter re-sizes the window.
**
** Neat, HUH !!!
**
** By the way, with QuickTime, version 1.0, to send the above action message,
** all I needed to do was to call _MCSetControllerBoundsRect. NO MO!!! */
err = MCGetControllerBoundsRect(localMC, &controllerBox);
FailOSErr(err);
OffsetRect(&controllerBox, -controllerBox.left, -controllerBox.top);
UnionRect(&moovBox, &controllerBox, &both);
/* Send mcActionControllerSizeChanged to my MCFilter
** so my Window can be re-sized proportionally: */
err = MCDoAction(localMC, mcActionControllerSizeChanged, &both);
if (err == noErr ||
err == controllerBoundsNotExact /* Controller Manager made it exact */)
err = MCMovieChanged(localMC, localMoov);
FailOSErr(err);
} /* PrepCombinedMovieAndController */
void CMovie::PlayMovie (void) {
Movie activeMoov = GetMovie();
MovieController activeMC = GetController();
OSErr err;
GrafPtr currentPort = GetMacPort();
GDHandle currentDevice = nil;
TimeValue startTime = 0,
currentTime,
noDuration = 0;
Fixed rate = 0;
long maxSleep;
HideCursor(); /* TOO MUCH fluttering !!! */
// Play the movie in the window:
SetMovieGWorld(activeMoov, (CGrafPtr) currentPort, currentDevice);
FailOSErr( GetMoviesError() ); // NEVER returns if an error !!!
// Now we're ready to play the movie:
GoToBeginningOfMovie(activeMoov);
FailOSErr( GetMoviesError() );
/* StartMovie does these:
PrerollMovie(activeMoov, startTime, rate); // Get the movie ready to play.
FailOSErr( GetMoviesError() );
SetMovieActive(activeMoov, true);
FailOSErr( GetMoviesError() ); */
StartMovie(activeMoov); // Start the movie.
FailOSErr( GetMoviesError() );
/* Play the movie until done or the mouse button has been pressed */
while ( !IsMovieDone(activeMoov) && !Button() )
Dawdle(&maxSleep);
if (IsMovieDone(activeMoov)) {
GoToBeginningOfMovie(activeMoov); // ... otherwise we stay at end.
FailOSErr( GetMoviesError() );
/* ... otherwise we play it AGAIN ????? */
StopMovie(activeMoov);
FailOSErr( GetMoviesError() );
/* Redraw so Controller Bar's Thumb appears at beginning: */
Dawdle(&maxSleep);
}
// Set selection to zero, otherwise WHOLE Movie is selected:
currentTime = GetMovieTime(activeMoov, nil /* don't need TimeRecord */);
FailOSErr( GetMoviesError() );
SetMovieSelection(activeMoov, currentTime, noDuration);
FailOSErr( GetMoviesError() );
Activate(); // So new selection shows.
ShowCursor();
} /* PlayMovie */
void CMovie::DisposMoovie (void) {
Movie localMoov = GetMovie();
if (localMoov) {
/* MCCut & MCClear effectively void the Movie by setting
** its duration = 0. In short, it's really gone !!! */
if (GetMovieDuration(localMoov) != 0) {
DisposeMovie(localMoov);
FailOSErr( GetMoviesError() );
}
moov = nil; // Mark as gone !!!
}
} /* DisposMoovie */
void CMovie::DisposController (void) {
MovieController localMC = GetController();
if (localMC != NULL) {
DisposeMovieController(localMC);
FailOSErr( GetMoviesError() );
mc = nil; // See ya around !!!
}
} /* DisposController */
static pascal Boolean MCFilter (MovieController mcPlay, short *Action,
long params) {
/* purpose: This function gets called whenever the controller is about
** to perform an action. Here we use it to resize the window
** in response to an Editing action, e.g, cutting and pasting. */
Rect moovBox, controllerBox, newWindowPortRect;
Movie localMoov;
TimeRecord currentTime;
TimeValue now;
OSErr err;
CGrafPtr mcPort;
CWindow *mcWind;
CMovie *theMoviePane;
// Retrieve some common parms:
mcPort = MCGetControllerPort(mcPlay);
if (mcPort == nil) return; // Is this possible ???
localMoov = MCGetMovie(mcPlay);
if (GetMoviesError() != noErr) {
SysBeep(10);
return;
}
mcWind = (CWindow*) GetWRefCon((GrafPtr) mcPort);
// Because we will be drawing into the window directly with action = mcActionKey:
mcWind->ForceNextPrepare();
theMoviePane = (CMovie*) gGopher;
switch (*Action) {
case mcActionControllerSizeChanged:
/* Controller rect includes BOTH the Controller Bar
** AND the Movie (if one exists): */
err = MCGetControllerBoundsRect(mcPlay, &controllerBox);
if (err != noErr) {
SysBeep(10);
break;
}
GetMovieBox(localMoov, &moovBox);
if (GetMoviesError() != noErr) {
SysBeep(10);
break;
}
/* Screwy things happen when we paste a Movie into a Movie window
** wherein the Controller Bar is NOT showing, that is, when the
** Badge IS showing. Ditto for cutting a Movie which stands to
** reason because before we call MCPaste we call ClearSelection
** which calls MCClear. MCClear AND its companion, MCCut,
** therefore, appear to hold the common denominator.
**
** I do NOT know what the real problem is, but my solution is to
** make the Controller Bar always visible after a cut or clear. */
if (MCGetVisible(mcPlay) == 0) { // controller is invisible.
if ( EmptyRect(&moovBox) /* just called MCCut or MCClear */ ) {
/* empty Movie has a rect = {1,1,1,1} */
MCSetVisible(mcPlay, true);
newWindowPortRect = controllerBox;
}
else {
/* We just clicked in the Movie with the <Option>
** key pressed to make the Badge appear: */
newWindowPortRect = moovBox;
}
}
else /* Controller is visible */ newWindowPortRect = controllerBox;
mcWind->ChangeSize(newWindowPortRect.right - newWindowPortRect.left,
newWindowPortRect.bottom - newWindowPortRect.top);
/*
** With this here and the <Option> key pressed, Badge
** shows and then IMMEDIATELY disappears ?????
MCMovieChanged(mcPlay, localMoov);
*/
return (FALSE); // This action does not handle events.
break; /* mcActionControllerSizeChanged */
case mcActionKey:
// params = a pointer to the EventRecord:
if (GetMovieDuration(localMoov) > 0) {
if ( KeyIsDown(KeyLeftCursor) || KeyIsDown(KeyDownCursor) ) {
theMoviePane->Prepare();
while ((KeyIsDown(KeyLeftCursor) || KeyIsDown(KeyDownCursor)) &&
GetMovieTime (localMoov, ¤tTime) > 0) {
MCDoAction(mcPlay, mcActionStep, (void*) ((Fixed)-1));
MCIdle(mcPlay);
}
}
else if ( KeyIsDown(KeyRightCursor) || KeyIsDown(KeyUpCursor) ) {
theMoviePane->Prepare();
while ((KeyIsDown(KeyRightCursor) || KeyIsDown(KeyUpCursor)) &&
!IsMovieDone(localMoov)) {
MCDoAction(mcPlay, mcActionStep, (void*) ((Fixed)1));
MCIdle(mcPlay);
}
}
} /* duration > 0 */
return (TRUE);
break; /* mcActionKey */
default:
return (FALSE); // Pass it on.
} /* end: switch */
} /* MCFilter */
ComponentResult CMovie::SetUpFilter (Boolean which) {
/* purpose: Shows how to set up an ActionFilter.
** In this sample the filter is used to resize the window
** when the controller is hidden to show badges. */
MovieController localMC = GetController();
Boolean mine = true,
defaultFilter = !mine /* Use Apple's */;
MCActionFilter whichFilter =
(which == mine) ? (MCActionFilter) &MCFilter : nil;
return ( MCSetActionFilter(localMC, whichFilter) );
} /* SetUpFilter */
ComponentResult CMovie::ShowBadge (Boolean doShow) {
/* purpose: Shows how to use the MCDoAction routine to
** select the behavior of the controller. */
Boolean params = doShow;
MovieController localMC = GetController();
// The action mcActionSetUseBadge takes a boolean as the parameter:
return ( MCDoAction(localMC, mcActionSetUseBadge, (void*) params) );
} /* ShowBadge */
ComponentResult CMovie::EnableKeys (Boolean doEnable) {
Boolean params = doEnable;
MovieController localMC = GetController();
// The action mcActionSetKeysEnabled takes a boolean as the parameter:
return ( MCDoAction(localMC, mcActionSetKeysEnabled, (void*) params) );
} /* EnableKeys */
// OVERRIDE
void CMovie::Activate (void) {
MovieController localMC = GetController();
GrafPtr localPort = GetMacPort();
inherited::Activate(); // Calls ForceNextPrepare & sets CView::active.
justActivated = true; // For my special CView::DispatchCursor.
if (localMC) {
Prepare(); /* ... since MCActivate draws directly
** in the Port. Also calls SetPort. */
MCActivate(localMC, localPort, true);
}
} /* Activate */
// OVERRIDE
void CMovie::Deactivate (void) {
MovieController localMC = GetController();
GrafPtr localPort = GetMacPort();
inherited::Deactivate();
if (localMC) {
Prepare();
MCActivate(localMC, localPort, false);
}
} /* Deactivate */
// OVERRIDE
void CMovie::Draw (Rect *area) {
Movie localMoov = GetMovie();
MovieController localMC = GetController();
GrafPtr localPort = GetMacPort();
if (localMC != nil) {
/* Will update any attached Movie: */
MCDraw(localMC, localPort);
}
else if (localMoov != nil) {
UpdateMovie(localMoov);
}
// else inherited::Draw(area); -- CPane::Draw is empty.
} /* Draw */
// OVERRIDE
void CMovie::DoClick (Point hitPt, short modifierKeys, long when) {
/* With the Badge showing and therefore the Controller Bar NOT,
** MCClick does all the work ... double clicking somewhere in
** the Movie, but NOT on the badge, causes the Movie to play ...
** clicking on the Badge causes the Controller Bar to appear and
** the Badge to disappear.
**
** With the Controller Bar showing and therefore the Badge NOT,
** clicking in the Controller Bar is also totally handled by MCClick.
** Samo Samo for clicking in the Movie above the Controller Bar with
** no <Option Key> pressed. But, courtesy of yours truly, if the
** <Option Key> IS pressed, the Controller Bar disappears. If the
** Controller Bar is not visible, QuickTime makes the Badge re-appear: */
Movie localMoov = GetMovie();
MovieController localMC = GetController();
ComponentResult mcVis = MCGetVisible(localMC);
Boolean usingBadge = false,
toggle = (mcVis == 0) ? true : false;
GrafPtr localPort = GetMacPort();
LongRect moovFox;
Rect moovQox, windRect;
LongPt framePt;
Point windPt;
if (localMC) {
QDToFrame(hitPt, &framePt);
FrameToWind(&framePt, &windPt);
if (mcVis == 0)
MCClick(localMC, localPort, windPt, when, modifierKeys);
else /* Controller is visible */ {
/* You would also come here if the entire Movie had been cut
** or cleared or if you had simply created a brand new Movie.
** The latter creates a new Movie whose box has zero-extent
** = {1,1,1,1}. The Movie's duration is also set = 0. */
if (localMoov && GetMovieDuration(localMoov) > 0) {
GetMovieBox(localMoov, &moovQox);
FailOSErr( GetMoviesError() );
QDToFrameR(&moovQox, &moovFox);
FrameToWindR(&moovFox, &windRect);
if ( PtInRect(windPt, &windRect) ) {
if ( MCDoAction(localMC, mcActionGetUseBadge, &usingBadge) ==
(ComponentResult) noErr ) {
if ( (modifierKeys & optionKey) && usingBadge )
// Automatically makes the Badge appear or disappear:
MCSetVisible(localMC, toggle);
else
MCClick(localMC, localPort, windPt, when, modifierKeys);
}
else
MCClick(localMC, localPort, windPt, when, modifierKeys);
}
else {
/* Clicked on the Controller Bar itself,
** vice just on the Movie above it: */
MCClick(localMC, localPort, windPt, when, modifierKeys);
}
} /* Got a Movie */
} /* Controller is visible */
} /* localMC */
else inherited::DoClick(hitPt, modifierKeys, when); // EMPTY for now !!
} /* DoClick */
// OVERRIDE
void CMovie::DoKeyDown (char theChar, Byte keyCode, EventRecord *macEvent) {
MovieController localMC = GetController();
Boolean keysEnabled = false;
short localModifiers = macEvent->modifiers;
if (localMC) {
if ( MCDoAction(localMC, mcActionGetKeysEnabled, &keysEnabled) ==
(ComponentResult) noErr )
if (keysEnabled) MCKey(localMC, keyCode, localModifiers);
}
/*
** MUST pass up the chain to CBureaucrat which implements:
**
** itsSupervisor->DoKeyDown(...);
**
** where this "itsSupervisor" is my CQuickTime document.
** Since a CDocument is a CBureaucrat, CBureaucrat::DoKeyDown
** gets called AGAIN. This time, however, "itsSupervisor" is
** my application since a CApplication supervises a CDocument.
**
** In short, I must pass DoKeyDown UP to my application:
*/
inherited::DoKeyDown(theChar, keyCode, macEvent);
} /* DoKeyDown */
// OVERRIDE
void CMovie::Dawdle (long *maxSleep) {
Movie localMoov = GetMovie();
MovieController localMC = GetController();
inherited::Dawdle(maxSleep); // Currently EMPTY !!!
*maxSleep = maxMilliSecToUse;
if (localMC != nil) {
if (MCIdle(localMC) == mcHandledEvent) // Calls MoviesTask.
;
// MCDoAction(localMC, mcActionShowBalloon, &gBalloonsUp); -- NOT needed ???
}
else if (localMoov != nil) MoviesTask(localMoov, maxMilliSecToUse);
} /* Dawdle */
/*********************************************************************************
DispatchCursor
Mouse is inside view and the cursor shape needs to be adjusted. Find out
if a subview can set the cursor shape. If not, send message to ourself to
handle it.
According to the TCL Manual, AdjustCursor get called ONLY when we leave our
CPane AND re-enter. Looking at the original TCL source code as well as
"following the bouncing ball" via the TCL Debugger, it is clear that we are
called everytime even if the blasted mouse has NOT moved. Symantec's Tech
Support has confirmed this. My suspicion is that the TCL Manual was written
when DispatchCursor was called in response to a "mouseMovedMessage" Event
generated by _WaitNextEvent. To correct this deficiency, I rewrote
DispatchCursor so that it does simulate a "mouseMovedMessage" Event.
Do NOT rewrite TCL's CView::DispatchCursor for your own program; rather write
CYourView::DispatchCursor or CYourPane::DispatchCursor. Only Symantec should
fiddle with TCL's CView method.
*********************************************************************************/
/*
** Find area of View not covered by subviews:
*/
static void SubView_Frame (CView *theView, RgnHandle uncovered) {
LongRect frameR;
Rect globalR;
if (theView->IsVisible() && theView->wantsClicks) {
theView->GetFrame(&frameR);
theView->FrameToGlobalR(&frameR, &globalR);
RectRgn(gUtilRgn, &globalR);
DiffRgn(uncovered, gUtilRgn, uncovered);
}
} /* SubView_Frame */
void CMovie::DispatchCursor (
Point where, /* Mouse location in Window coords */
RgnHandle mouseRgn) /* Region containing the mouse */
{
CView *hitView; /* View containing the mouse */
LongRect frameAperture;
Rect globalAperture;
RgnHandle apertureRgn;
static RgnHandle prevMouseRgn = NULL;
GrafPtr savePort;
static GrafPtr prevWindow = NULL;
Point saveOrigin, offsetOrigin, offsetGlobal, globWhere;
Boolean mouseHasMoved, firstTime;
hitView = FindSubview(where); /* See if mouse is within a subview. */
if (hitView == NULL) { /* Mouse not within a deeper subview,
** but within THIS one. */
// Wish I could avoid all this memory overhead, but ...
apertureRgn = NewRgn();
GetAperture(&frameAperture); /* Start off with the aperture */
/* in global coordinates. */
FrameToGlobalR(&frameAperture, &globalAperture);
RectRgn(apertureRgn, &globalAperture);
// Calculate the uncovered area of this View:
if (itsSubviews != NULL) { /* Substract the area covered by */
/* the frames of its subviews */
itsSubviews->DoForEach1((EachFunc1) SubView_Frame, (long)apertureRgn);
}
/* Now take intersection with the visRgn of View's port. There could
** be something, such as a window, floating above the View. Unfortunately,
** the visRgn is the local coordinates and we need it to be in global
** coordinates. Rather than making a copy and offsetting to global
** coords, we temporily shift the View's port so that its local coords
** are the same as global coords. This saves us the overhead of making
** a copy of the visRgn, which may take up a lot of memory, at the
** expense of having to save and restore the port and origin. */
GetPort(&savePort); /* Save port and origin. */
SetPort(macPort);
offsetOrigin = saveOrigin = topLeft(macPort->portRect);
LocalToGlobal(&offsetOrigin);
SetOrigin(offsetOrigin.h, offsetOrigin.v);
/* visRgn is in Global coords now. */
SectRgn(macPort->visRgn, apertureRgn, apertureRgn);
/* Restore origin and port. */
SetOrigin(saveOrigin.h, saveOrigin.v);
SetPort(savePort);
offsetGlobal = topLeft( (**((WindowPeek)macPort)->contRgn).rgnBBox );
globWhere = where;
globWhere.h += offsetGlobal.h;
globWhere.v += offsetGlobal.v;
firstTime = (macPort != prevWindow) || justSaved || justActivated;
if (firstTime) {
if (prevMouseRgn == NULL) prevMouseRgn = NewRgn();
CopyRgn(mouseRgn, prevMouseRgn);
}
;
mouseHasMoved = !EqualRgn(mouseRgn, prevMouseRgn) ||
!PtInRgn(globWhere, prevMouseRgn);
if (firstTime || mouseHasMoved) {
CopyRgn(apertureRgn, mouseRgn);
AdjustCursor(where, mouseRgn);
CopyRgn(mouseRgn, prevMouseRgn);
}
;
prevWindow = macPort;
justSaved = false;
justActivated = false;
/*
** gUtilRgn is a universally available RgnHandle that is setup
** by CApplication::IApplication via a call to NewRgn and is
** NOT and need not be disposed of by the TCL. The final call
** to _ExitToShell tacked onto the end of the compiled code
** will automatically dispose of any handles on the Application
** heap. The same holds true for gApplication, gBartender,
** gClipboard, gGopher and the remaining global objects.
**
** DisposeRgn(gUtilRgn);
*/
SetEmptyRgn(gUtilRgn); // Do this instead !!
DisposeRgn(apertureRgn); // We're finished with this also.
/* DisposeRgn(prevMouseRgn); // Let _ExitToShell take care of
** // this since I still need it. */
}
else { /* Mouse is within a subview. */
hitView->DispatchCursor(where, mouseRgn);
}
/* If balloons are on and no one has shown a balloon, then do it now.
** This could either be because the mouse is not in a subview or because
** no subview did help. This allows a group of panes to share the same help
** balloon by putting the help info in their enclosing view. */
if (gSystem.hasHelpMgr && HMGetBalloons() && !cCurrHelpView) {
Rect r;
HMMessageRecord helpData;
Point globalMouse;
Ptr tipProc = NULL;
short bProc, bVariant, bMethod;
helpData.hmmHelpType = 0;
GetBalloonInfo(&helpData, &globalMouse, &r, &tipProc,
&bProc, &bVariant, &bMethod);
ShowHelpBalloon(&helpData, globalMouse, &r, tipProc,
bProc, bVariant, bMethod);
}
} /* DispatchCursor */
// OVERRIDE
void CMovie::AdjustCursor (Point where, RgnHandle mouseRgn) {
/* This seems as good a place as any for a tracing lesson:
**
** IPaneX() calls CalcAperture which calls itsEnclosure->GetAperture. Since
** itsEnclosure is of class CWindow, we are calling CWindow::GetAperture which
** sets the aperture = the portRect, offset so the topLeft of the aperture = {0, 0}.
** CalcAperture continues by converting the aperture returned by GetAperture to
** frame coordinates. CalcAperture then computes the intersection of the frame &
** the returned aperture and fills in the instance variable = CPane::aperture.
**
** BUT ... initially the frame = nil since we passed width = height = 0 to IPane(...).
** However, after calling IPane, we call FitToEnclosure. The latter retrieves the
** Window's interior = portRect and converts it to frame coordinates. FitToEnclosure
** finishes by calling ChangeSize and passes to the latter the window's portRect in
** frame coordinates. ChangeSize calls ResizeFrame which sets the width, height and
** frame instance variables of CPane accordingly ... so we've got a finite frame
** finally. CalcAperture gets called AGAIN so we get a finite aperture as well.
**
** How does my CMovie's AdjustCursor finally get called? When IPane is called by
** IMovie, IView gets called to setup CView::itsEnclosure and
** CBureaucrat::itsSupervisor. IPane then calls IPaneX() which calls:
** itsEnclosure->AddSubView(this);
** where "this" = my CMovie CPane and itsEnclosure = my window. AddSubView
** initializes CView::itsSubViews by calling IList and adds "this" to the CList =
** itsSubViews.
**
** Within CApplication::Run():
** itsSwitchboard->ProcessEvent();
** is called. The latter calls:
** gDesktop->DispatchCursor(...);
** which calls CWindow's DispatchCursor which then calls CView's DispatchCursor.
** The latter calls FindSubView and upon finding that the mouse is within my
** CMovie CPane, returns hitView = CMovie CPane. hitView->DispatchCursor is called
** and since hitView = CMovie, in effect CMovie->DispatchCursor is being called.
** CMovie has no DispatchCursor method, so this method is inherited from CView.
** The object that was sent the message = DispatchCursor is my CMovie, so when CView's
** DispatchCursor finds no more sub-views, the latter calls AdjustCursor. This
** call could have been written:
** this->AdjustCursor(...);
** where "this" = the object that was sent the ORIGINAL message = DispatchCursor.
** Since "this" = my CMovie, my CMovie::AdjustCursor gets called.
**
** According to the TCL Manual, we get called ONLY when we leave this CMovie pane
** AND re-enter. We called GetCCursor once and ONLY once within our IStarterApp
** and will call SetCCursor any number of times below. All of this is according
** to the Hoyle stipulated in IM V.
**
** What I have NOT been able to figure out yet is how we get called ONLY when we
** leave this CMovie pane AND re-enter. Looking at the original TCL source code
** as well as "following the bouncing ball" via the TCL Debugger, it appears that
** we are called everytime even if the blasted mouse has NOT moved. Symantec has
** confirmed this. My suspicion is that the TCL Manual was written when
** DispatchCursor was called in response to a "mouseMovedMessage" Event generated
** by _WaitNextEvent. To correct this deficiency, I rewrote DispatchCursor so
** that it does simulate a "mouseMovedMessage" Event. */
// #define kCameraCursor 3006
Movie localMoov = GetMovie();
Rect mouseRect, moovBox, globalRect;
LongPt locWhere;
LongRect moovFRect, framePart;
if (localMoov == NULL) {
inherited::AdjustCursor(where, mouseRgn); // Calls SetCursor(&arrow).
return;
}
// Get the WHOLE frame at first, but just the visible portion:
GetFrame(&framePart);
SectLongRect(&framePart, &aperture, &framePart);
;
// Now just the visible part of the Movie:
GetMovieBox(localMoov, &moovBox);
// FailOSErr( GetMoviesError() ); -- NO danger here !!
QDToFrameR(&moovBox, &moovFRect);
SectLongRect(&moovFRect, &aperture, &moovFRect);
;
WindToFrame(where, &locWhere);
if ( PtInLongRect(&locWhere, &moovFRect) ) {
if (niftyCameraCRSR != NULL) /* We've got a color Mac. */ {
LoadResource(niftyCameraCRSR); // May have been purged.
SetCCursor(niftyCameraCRSR);
}
else SetCursor(*gCameraCursor);
framePart.bottom = moovFRect.bottom;
}
else /* in just the Controller Bar */ {
SetCursor(&arrow);
framePart.top = moovFRect.bottom;
}
/* Change the passed "mouseRgn" so that my newly rewritten
** DispatchCursor calls AdjustCursor ONLY if the mouse has moved: */
FrameToGlobalR(&framePart, &globalRect); // Convert to global coords …
RectRgn(mouseRgn, &globalRect);
} /* AdjustCursor */
// OVERRIDE
void CMovie::UpdateMenus (void) {
Movie localMoov = GetMovie();
MovieController localMC = GetController();
TimeValue atBeginning = 0, lengthMovie,
currSelectionTime, currSelectionDuration,
currentTime, nextTime, nextDuration;
Fixed movieRate;
short allMedia = 0;
OSType allTypes = 0;
inherited::UpdateMenus(); // Enable standard commands.
ShiftKeyIsDownToSelectWholeMovie = KeyIsDown(KeyShift);
if (localMC) {
if ( MCIsEditingEnabled(localMC) ) {
/*
** Has NOT been Cut or Cleared or NOT a new window.
** Note that I also change the text of each MENU item
** because I prefer such phrases as "Nothing to Cut"
** in each MENU item when appropriate.
**
** Also note that placing such phrases just in the
** attached resource file is NOT ample because once
** SetCmdText is called, the MENU resource loaded
** in memory stays that way. Therefore, I need to
** call SetCmdText for all items, even if disabled.
**
** Anyway, I thought that overall it's a nice feature.
*/
if (localMoov) lengthMovie = GetMovieDuration(localMoov);
else lengthMovie = -1;
if (lengthMovie > 0) {
if (ShiftKeyIsDownToSelectWholeMovie)
gBartender->SetCmdText(cmdCut, "\pCut Entire Movie");
else
gBartender->SetCmdText(cmdCut, "\pCut Movie Frame(s)");
gBartender->EnableCmd(cmdCut);
;
if (ShiftKeyIsDownToSelectWholeMovie)
gBartender->SetCmdText(cmdCopy, "\pCopy Entire Movie");
else
gBartender->SetCmdText(cmdCopy, "\pCopy Movie Frame(s)");
gBartender->EnableCmd(cmdCopy);
;
if (ShiftKeyIsDownToSelectWholeMovie)
gBartender->SetCmdText(cmdClear, "\pClear Entire Movie");
else
gBartender->SetCmdText(cmdClear, "\pClear Movie Frame(s)");
gBartender->EnableCmd(cmdClear);
}
else {
gBartender->SetCmdText(cmdCut, "\pNothing to Cut");
gBartender->SetCmdText(cmdCopy, "\pNothing to Copy");
gBartender->SetCmdText(cmdClear, "\pNothing to Clear");
}
// Can Paste into an empty Movie:
if (gClipboard->DataSize('moov') > 0) {
if (ShiftKeyIsDownToSelectWholeMovie)
gBartender->SetCmdText(cmdPaste, "\pPaste over Entire Movie");
else
gBartender->SetCmdText(cmdPaste, "\pPaste over Movie Frame(s)");
gBartender->EnableCmd(cmdPaste);
}
else
gBartender->SetCmdText(cmdPaste, "\pNothing to Paste");
/*
** inherited::UpdateMenus() propagates up to CBureaucrat::UpdateMenus
** which calls:
** itsSupervisor->UpdateMenus();
** Since "itsSupervisor" is my CQuickTime document,
** CQuickTime::UpdateMenus gets called. The latter calls:
** CDocument::UpdateMenus();
** which, if CDocument::lastTask != NULL, calls:
** CDocument::UpdateUndo().
** UpdateUndo sets the text of the Edit MENU's "Undo" item to
** "Undo Cut" or "Undo Paste", for example. In short, normally
** we do NOT need this here because it is duplicative. However,
** because of my innovative changing of item text as addressed
** above, I need it here. The only reason I need to duplicate
** the code here is for the case, lastTask = NULL; otherwise,
** UpdateUndo changes the text for me.
*/
if (lastMovieEditTask == NULL) {
gBartender->SetCmdText(cmdUndo, "\pNothing to Undo");
}
/* else {
gBartender->EnableCmd(cmdUndo);
( (CQuickTime*) itsSupervisor )->UpdateUndo();
} */
} /* editing is enabled */
gBartender->SetCmdText(cmdClose, "\pClose Movie");
if (lengthMovie > 0) {
GetMovieSelection(localMoov, &currSelectionTime, &currSelectionDuration);
FailOSErr( GetMoviesError() );
currentTime = GetMovieTime(localMoov, nil);
FailOSErr( GetMoviesError() );
movieRate = GetMovieRate(localMoov);
FailOSErr( GetMoviesError() );
GetMovieNextInterestingTime(localMoov, nextTimeMediaSample,
allMedia, &allTypes, currentTime,
movieRate, &nextTime, &nextDuration);
FailOSErr( GetMoviesError() );
;
gBartender->EnableCmd(cmdPlayForward);
gBartender->EnableCmd(cmdPlayBackward);
if (currentTime != atBeginning)
gBartender->EnableCmd(cmdGoToBeginning);
if (nextTime > 0) // See comment within CMovie::SetSelection.
gBartender->EnableCmd(cmdGoToEnd);
gBartender->EnableCmd(cmdGoToFrameNumber);
gBartender->EnableCmd(cmdSelectFrames);
if (currSelectionDuration > 0)
gBartender->EnableCmd(cmdDeselectFrames);
}
} /* localMC */
} /* UpdateMenus */
void CMovie::SetSelection (long theCommand) {
/* The various editing routines such as MCCut & MCClear work with
** the current selection, so we set the selection accordingly: */
Movie activeMoov = GetMovie();
MovieController activeMC = GetController();
TimeValue start, duration, lengthMovie,
currSelectionTime, currSelectionDuration, currentTime,
nextTime, nextDuration;
short allMedia = 0;
OSType allTypes = 0;
Fixed movieRate;
// if (activeMC == NULL || activeMoov == NULL) return; -- canNOT happen !!
lengthMovie = GetMovieDuration(activeMoov);
FailOSErr( GetMoviesError() );
/* Bet you thought I forgot about pasting into an empty Movie.
** NOT !!! because for an empty Movie, there is no selection. */
if (lengthMovie == 0) return;
GetMovieSelection (activeMoov, &currSelectionTime, &currSelectionDuration);
FailOSErr( GetMoviesError() );
if ( !ShiftKeyIsDownToSelectWholeMovie /* just a frame or two */ ) {
if (currSelectionDuration > 0 && currSelectionDuration <= lengthMovie) {
/* Frame(s) already selected. The user can force a
** selection of discrete frame(s) by clicking on either
** the <Forward> or <Backward> "Step" controls that are
** part of the Controller Bar while simultaneously pressing
** the <Shift> key, the 'ole' "Shift-Select" bit.
**
** If you feel so inclined, use the "Select Frames" item
** under the "Movie" Menu as a simpler way to accomplish
** the same thing. */
FramesPreSelected = true;
;
start = currSelectionTime;
duration = currSelectionDuration;
}
else /* select the frame you're staring at */ {
FramesPreSelected = false;
if (theCommand == cmdPaste) {
duration = 0;
/* Go forward one frame because unless we're at
** the very end of the Movie, the currentTime is
** the time BEFORE the viewed frame. The goal is
** to always paste AFTER the viewed frame. If
** we're at the bitter end, advancing one frame
** has no effect, so our goal is still achieved. */
MCDoAction(activeMC, mcActionStep, (void*) ((Fixed)1));
start = GetMovieTime(activeMoov, nil);
FailOSErr( GetMoviesError() );
}
else /* cutting, copying or clearing */ {
currentTime = GetMovieTime (activeMoov,
nil /* don't need TimeRecord */);
FailOSErr( GetMoviesError() );
movieRate = GetMovieRate(activeMoov);
FailOSErr( GetMoviesError() );
GetMovieNextInterestingTime(activeMoov, nextTimeMediaSample,
allMedia, &allTypes, currentTime,
movieRate, &nextTime, &nextDuration);
FailOSErr( GetMoviesError() );
if (nextTime > 0 /* && nextTime <= lengthMovie */) {
start = currentTime;
duration = nextTime - currentTime;
}
else {
/* There's an apparent problem ??FEATURE?? at the very
** end of the Movie because when you step either forward
** to or backward from the end, the last frame shows
** TWICE. This last frame does not exist twice, it just
** appears twice. In this instance, "nextTime" is negative.
** This problem does NOT occur at the beginning, that is,
** the first frame does not show twice. */
// ... so go the bitter end & THEN backup:
GoToEndOfMovie(activeMoov);
FailOSErr( GetMoviesError() );
MCDoAction(activeMC, mcActionStep, (void*) ((Fixed)-1));
start = GetMovieTime(activeMoov, nil);
FailOSErr( GetMoviesError() );
duration = lengthMovie - start;
}
} /* NOT pasting */
} /* just select one frame */
}
else /* <Shift> key pressed to select the WHOLE thing! */ {
start = 0;
duration = lengthMovie;
}
SetMovieSelection(activeMoov, start, duration);
FailOSErr( GetMoviesError() );
/*
** We do NOT have to reset the <Shift> key Boolean because
** the TCL always calls UpdateMenus in response to either
** a mouseDown in the MenuBar or a <CMD> keypress:
ShiftKeyIsDownToSelectWholeMovie = false;
*/
} /* SetSelection */
void CMovie::ClearSelection (void) {
/* The following is for pasting ONLY.
** It is NOT required for disposing: */
CWindow *movieWindow = GetWindow();
short numWindows;
Str255 Untitled = "\pUntitled",
numString,
newTitle;
MovieController activeMC = GetController();
Movie activeMoov = GetMovie();
TimeValue currentTime, movieDuration;
/* The if-clause IS necessary since CMovie::UpdateMenus
** enables "Paste" given a 'MooV' on the clipboard and
** since cmdPaste calls ClearSelection: */
if (
activeMC != NULL &&
activeMoov != NULL &&
GetMovieDuration(activeMoov) > 0
) {
// Otherwise, nothing to clear
GetMovieSelection(activeMoov, ¤tTime, &movieDuration);
FailOSErr( GetMoviesError() );
if (movieDuration > 0) {
MCClear(activeMC);
FailOSErr( GetMoviesError() );
}
}
/* Do NOT change window's title because I call this when pasting.
numWindows = ++(gDecorator->wCount); // See comments within INewQuickTime.
NumToString(numWindows, numString);
CopyPString(Untitled, newTitle);
ConcatPStrings(newTitle, "\p - ");
ConcatPStrings(newTitle, numString);
movieWindow->SetTitle(newTitle);
*/
} /* ClearSelection */
// OVERRIDE
void CMovie::DoCommand (long theCommand) {
enum
{
okGoTo = cmdOK, cancelGoTo, // "Go To Frame" DLOG ...
iconGoTo = 3,
goToEdit,
okSelect = cmdOK, cancelSelect, // "Select Frames" DLOG ...
iconSelect = 3,
selectFromStat, selectFromEdit,
selectToStat, selectToEdit
};
Movie activeMoov, scrapMoov;
MovieController activeMC;
TimeValue atBeginning = 0,
noSelection = 0,
lengthMovie,
currSelectionTime, currSelectionDuration,
currentTime, nextTime,
fromTime, toTime,
newDuration, nextDuration;
Fixed movieRate;
short allMedia = 0;
OSType allTypes = 0;
CWindow *theWindow = GetWindow();
GrafPtr localPort = GetMacPort();
OSErr err;
long zeroFlags = 0, dlogCommand;
CQuickTime *myDoc = (CQuickTime*) GetSupervisor();
Boolean prevDirty;
CMovieDLOGDir *movieDLOGDir = NULL;
CIntegerText *goToText, *selectFromText, *selectToText;
long goToValue, selectFromValue, selectToValue,
frameCount, swap;
/* This should NOT happen because UpdateMenus will NOT
** enable any Edit MENU items if active Controller = NULL: */
if ( myDoc->itsMovie == NULL ||
(activeMC = GetController()) == NULL ) {
inherited::DoCommand(theCommand);
return;
}
/* Note that I do NOT test for a zero-duration "activeMoov" because
** pasting still works for such a beast. With regards to cutting,
** copying and clearing, CMovie::UpdateMenus will disable these
** commands for an empty Movie so they don't apply anyway. */
activeMoov = GetMovie();
switch (theCommand) {
/* Will eventually propagate up to CDocument::DoCommand
case cmdUndo:
if (lastTask != NULL) {
if (undone) lastTask->Redo();
else lastTask->Undo();
undone = !undone;
UpdateUndo();
}
break;
*/
case cmdCut:
/* Returns a new copy of the attached Movie, so after we place
** the copy on the public Scrap we must dispose of it. We can
** dispose of the cut or removed Movie because PutMovieOnScrap
** creates a new Movie based on the one cut ... so the one
** placed on the Scrap is in addition to our "scrapMoov".
**
** If you selected the ENTIRE Movie by pressing the <Shift> key
** while making your Menu selection, the duration of the original
** Movie, the one that was cut, is set = 0; however, the "moov"
** still exists and so does the Movie Controller = "mc".
** Furthermore, if you tried to open a new Movie file with the
** file having the cut Movie still open, the name of the latter
** would NOT appear in the SFGetFile list because it's still
** there even if its duration = 0.
**
** Oh ... one more thing ... MCCut and MCClear will send a
** mcActionControllerSizeChanged message to my MCFilter which
** resizes my window accordingly. Note that the window will be
** VERY short if you selected the WHOLE Movie because there's no
** longer a Movie attached to the Controller. Furthermore, the
** sizebox disappears because the Movie is gone. There's nothing
** to resize, right? RIGHT!! */
/*
theWindow->HideSuspend(); ** Initially, I did the ugly stuff
** off-screen. Later I decided that
** it didn't look bad at all.
*/
SetSelection(cmdCut);
/* Fill in CMovie::lastMovieEditTask,
** record the current Scrap for UNdoing
** and record the in-place Movie: */
MakeMovieEditTask(cmdCut);
scrapMoov = MCCut(activeMC);
FailOSErr( GetMoviesError() );
/* Clear existing Scrap before adding +
** Copy Movie and MoviePoster in 'PICT' format: */
err = PutMovieOnScrap(scrapMoov, zeroFlags);
FailOSErr(err);
/* Dispose of the original Scrap because PutMovieOnScrap
** creates a copy and places the copy on the Scrap. */
DisposeMovie(scrapMoov);
FailOSErr( GetMoviesError() );
/* Notify propagates up to CBureaucrat::Notify which calls:
** itsSupervisor->Notify(...);
** So CDocument::Notify gets called and the latter sets
** CDocument::lastTask = the passed editTask after it
** disposes of the previous lastTask if there's one.
** Remember, IDocument sets lastTask = NULL. Notify also
** sets CDocument's undone to FALSE and dirty to TRUE. */
Notify(lastMovieEditTask);
lastMovieEditTask->Do();
// Where we're at !!!
GetMovieSelection(activeMoov, &currSelectionTime, &currSelectionDuration);
FailOSErr( GetMoviesError() );
SetMovieSelection(activeMoov, currSelectionTime, noSelection);
FailOSErr( GetMoviesError() );
Activate();
// theWindow->ShowResume();
break; /* cmdCut */
case cmdCopy:
SetSelection(cmdCopy);
MakeMovieEditTask(cmdCopy);
scrapMoov = MCCopy(activeMC);
FailOSErr( GetMoviesError() );
FailOSErr( PutMovieOnScrap(scrapMoov, zeroFlags) );
DisposeMovie(scrapMoov); // Get rid of the 1st copy after a
FailOSErr( GetMoviesError() ); // 2nd copy is placed on the Scrap.
prevDirty = myDoc->dirty;
;
Notify(lastMovieEditTask);
;
/* If the doc was previously dirty, for example, from
** a Paste operation, then we should maintain it: */
myDoc->dirty = prevDirty; // ... otherwise, Mr. CLEAN !!!
lastMovieEditTask->Do();
currentTime = GetMovieTime(activeMoov, nil);
FailOSErr( GetMoviesError() );
;
if (ShiftKeyIsDownToSelectWholeMovie || !FramesPreSelected)
{
SetMovieSelection(activeMoov, currentTime, noSelection);
FailOSErr( GetMoviesError() );
Activate();
}
else
{
// Leave selection alone !!
}
break; /* cmdCopy */
case cmdPaste:
/* Pasting really does look ugly WHEN we've selected the
** ENTIRE Movie and there's a Movie already there. In this
** instance ClearSelection will call MCClear which resizes
** the window down. MCPaste below will resize the window
** back up ... I didn't like seeing two changes in size. */
if (ShiftKeyIsDownToSelectWholeMovie) theWindow->HideSuspend();
SetSelection(cmdPaste);
MakeMovieEditTask(cmdPaste);
/* First get rid of what's preselected, if anything.
** The QuickTime docs state that MCPaste is analogous
** to PasteMovieSelection which will paste OVER any
** pre-selected frames. I have discovered that this
** does NOT appear to be true. */
ClearSelection();
scrapMoov = NewMovieFromScrap(newMovieActive);
FailOSErr( GetMoviesError() );
;
MCPaste(activeMC,scrapMoov);
FailOSErr( GetMoviesError() );
DisposeMovie(scrapMoov);
FailOSErr( GetMoviesError() );
Notify(lastMovieEditTask);
lastMovieEditTask->Do();
GetMovieSelection(activeMoov, &currSelectionTime, &currSelectionDuration);
FailOSErr( GetMoviesError() );
SetMovieSelection(activeMoov, currSelectionTime, noSelection);
FailOSErr( GetMoviesError() );
Activate();
if (ShiftKeyIsDownToSelectWholeMovie)
// Generates an update Event:
theWindow->ShowResume();
break; /* cmdPaste */
case cmdClear:
SetSelection(cmdClear);
MakeMovieEditTask(cmdClear);
/* Once again, if I've chosen to clear the WHOLE Movie
** by pressing the <Shift> key, the resulting Movie's
** duration is set = 0. However, the Movie is NOT and
** SHOULD not be disposed of. Note that I do NOT call
** PutMovieOnScrap so the existing contents of the
** public Scrap remain intact: */
MCClear(activeMC);
FailOSErr( GetMoviesError() );
Notify(lastMovieEditTask);
lastMovieEditTask->Do();
GetMovieSelection(activeMoov, &currSelectionTime, &currSelectionDuration);
FailOSErr( GetMoviesError() );
SetMovieSelection(activeMoov, currSelectionTime, noSelection);
FailOSErr( GetMoviesError() );
Activate();
break; /* cmdClear */
case cmdPlayForward:
// HideCursor(); -- not this time, folks !!!
/* Stop the Movie just in case it is playing.
** Call MCDoAction rather than StopMovie so the
** Pause Button on the Movie Controller bar
** changes back to a Play Button: */
MCDoAction(activeMC, mcActionPlay, (void*) 0 /* = stop Movie */);
FailOSErr( GetMoviesError() );
GoToBeginningOfMovie(activeMoov);
FailOSErr( GetMoviesError() );
movieRate = GetMoviePreferredRate(activeMoov);
FailOSErr( GetMoviesError() );
/* Do this, rather than call StartMovie, in order to
** display the Pause button on the Movie Controller bar: */
MCDoAction(activeMC, mcActionPlay, (void*) movieRate);
break; /* cmdPlayForward */
case cmdPlayBackward:
MCDoAction(activeMC, mcActionPlay, (void*) 0);
FailOSErr( GetMoviesError() );
GoToEndOfMovie(activeMoov);
FailOSErr( GetMoviesError() );
movieRate = GetMoviePreferredRate(activeMoov);
FailOSErr( GetMoviesError() );
MCDoAction(activeMC, mcActionPlay, (void*) -movieRate);
break; /* cmdPlayBackward */
case cmdGoToBeginning:
MCDoAction(activeMC, mcActionPlay, (void*) 0);
FailOSErr( GetMoviesError() );
GoToBeginningOfMovie(activeMoov);
FailOSErr( GetMoviesError() );
break; /* cmdGoToBeginning */
case cmdGoToEnd:
MCDoAction(activeMC, mcActionPlay, (void*) 0);
FailOSErr( GetMoviesError() );
GoToEndOfMovie(activeMoov);
FailOSErr( GetMoviesError() );
break; /* cmdGoToEnd */
case cmdGoToFrameNumber:
movieDLOGDir = new (CMovieDLOGDir);
movieDLOGDir->IMovieDLOGDir(kGoToFrame);
/*
** IMovieDLOGDir calls IDLOGDirector which:
**
** (a) sets CDirector::CDialogDirector::CDLOGDirector->itsWindow =
** new(CDLOGDialog);
** (b) calls IDLOGDialog which calls AddDITLItems
** (c) AddDITLItems then sets each View's ID =
** the item's index in the DITL resource.
*/
goToText = (CIntegerText*) movieDLOGDir->FindViewByID(goToEdit);
goToText->SetIntValue(1);
movieDLOGDir->BeginDialog();
dlogCommand = movieDLOGDir->DoModalDialog(okGoTo);
if (dlogCommand == okGoTo)
{
goToValue = goToText->GetIntValue();
if ( movieDLOGDir->Close(false /* NOT quitting */) )
{ // Inherited from CDialogDirector
theWindow->HideSuspend();
;
GoToBeginningOfMovie(activeMoov);
FailOSErr( GetMoviesError() );
lengthMovie = GetMovieDuration(activeMoov);
FailOSErr( GetMoviesError() );
for (frameCount = 1; frameCount < goToValue; frameCount++)
{
currentTime = GetMovieTime(activeMoov, nil);
FailOSErr( GetMoviesError() );
if (currentTime == lengthMovie)
{ /* Beyond the end. Note that MCDoAction will NOT
** bomb; however, needless time will be consumed. */
SysBeep(10);
break;
}
MCDoAction(activeMC, mcActionStep, (void*) ((Fixed) 1));
}
;
theWindow->ShowResume();
} /* Validation successful, so close the Dialog window */
else
{
/* Validation not successful, so keep
** window open and post an alert */
SysBeep(10);
}
}
else /* Cancel */
{
// SysBeep(10); -- already done by CMovieDLOGDir::DoCommand
movieDLOGDir->itsWindow->Dispose();
}
break; /* cmdGoToFrameNumber */
case cmdSelectFrames:
movieDLOGDir = new (CMovieDLOGDir);
movieDLOGDir->IMovieDLOGDir(kSelectFrames);
;
selectFromText = (CIntegerText*) movieDLOGDir->
FindViewByID(selectFromEdit);
selectFromText->SetIntValue(1);
selectToText = (CIntegerText*) movieDLOGDir->FindViewByID(selectToEdit);
selectToText->SetIntValue(1);
movieDLOGDir->BeginDialog();
dlogCommand = movieDLOGDir->DoModalDialog(okSelect);
if (dlogCommand == okSelect)
{
selectFromValue = selectFromText->GetIntValue();
selectToValue = selectToText->GetIntValue();
if (selectFromValue > selectToValue)
{
swap = selectFromValue;
selectFromValue = selectToValue;
selectToValue = swap;
}
if ( movieDLOGDir->Close(false) )
{
currentTime = atBeginning;
movieRate = GetMovieRate(activeMoov);
FailOSErr( GetMoviesError() );
;
for (
frameCount = 1;
frameCount < selectFromValue; // before the Frame.
frameCount++
)
{
GetMovieNextInterestingTime(activeMoov, nextTimeMediaSample,
allMedia, &allTypes, currentTime,
movieRate, &nextTime,
&nextDuration);
FailOSErr( GetMoviesError() );
if (nextTime < 0) break; // beyond the end.
currentTime = nextTime;
}
fromTime = currentTime;
;
currentTime = atBeginning;
for (
frameCount = 1;
frameCount <= selectToValue; // after the Frame.
frameCount++
)
{
if (currentTime < 0) break; // beyond the end.
GetMovieNextInterestingTime(activeMoov, nextTimeMediaSample,
allMedia, &allTypes, currentTime,
movieRate, &nextTime,
&nextDuration);
FailOSErr( GetMoviesError() );
currentTime = nextTime;
}
if (currentTime < 0) toTime = lengthMovie;
else toTime = currentTime;
;
GetMovieSelection(activeMoov, &currSelectionTime,
&currSelectionDuration);
FailOSErr( GetMoviesError() );
newDuration = toTime - fromTime;
SetMovieSelection(activeMoov, fromTime, newDuration);
FailOSErr( GetMoviesError() );
Activate();
} /* Validation successful, so close the Dialog window */
else
{
/* Validation not successful, so keep
** window open and post an alert */
SysBeep(10);
}
}
else if (dlogCommand == cmdSelectAll)
{
movieDLOGDir->itsWindow->Dispose();
lengthMovie = GetMovieDuration(activeMoov);
FailOSErr( GetMoviesError() );
SetMovieSelection(activeMoov, atBeginning, lengthMovie);
FailOSErr( GetMoviesError() );
Activate();
}
else /* Cancel */
{
// SysBeep(10); -- already done by CMovieDLOGDir::DoCommand
movieDLOGDir->itsWindow->Dispose();
}
break; /* cmdSelectFrames */
case cmdDeselectFrames:
GetMovieSelection(activeMoov, &currSelectionTime, &currSelectionDuration);
FailOSErr( GetMoviesError() );
SetMovieSelection(activeMoov, currSelectionTime, noSelection);
FailOSErr( GetMoviesError() );
Activate();
break; /* cmdDeselectFrames */
default:
inherited::DoCommand(theCommand);
break;
} /* end: switch */
} /* DoCommand */
void CMovieFile::IMovieFile (void) {
inherited::IResFile();
// refNum = noMoovFile; -- IResFile sets = 0.
resID = noMoovResource;
} /* IMovieFile */
// OVERRIDE
void CMovieFile::CreateNew (OSType creator, OSType fType) {
FSSpec movieSpec;
Movie theMoov = theMovie->GetMovie();
short rsrcID = 0; // Assign new unique ID.
GetFSSpec(&movieSpec);
FlattenMovie(
theMoov,
flattenAddMovieToDataFork /* for transfer to NON-Macs */,
&movieSpec,
creator,
iuSystemScript,
createMovieFileDeleteCurFile,
&rsrcID,
movieSpec.name
);
FailOSErr( GetMoviesError() );
resID = rsrcID;
} /* CreateNew */
// OVERRIDE
void CMovieFile::Open (SignedByte permission) {
FSSpec movieSpec;
OSErr err;
short movieFileRefNum;
if ( IsOpen() ) return;
GetFSSpec(&movieSpec);
err = OpenMovieFile(&movieSpec, &movieFileRefNum, permission);
if (err == noErr) refNum = movieFileRefNum;
else FailOSErr(err); /* Never returns:
** moov remains = nil &
** refNum = noMoovFile */
} /* Open */
// OVERRIDE
void CMovieFile::Close (void) {
short localMoovRefNum = refNum;
OSErr err = noErr;
if (localMoovRefNum != noMoovFile) { // 'tis open.
err = CloseMovieFile(localMoovRefNum);
if (err == noErr) {
refNum = noMoovFile; // Bye-Bye !!!
resID = noMoovResource;
// err = FlushVol("", volNum); -- ONLY saving should write-to-disk.
}
FailOSErr(err);
}
/* IResFile::Close() checks to see if CResFile::refNum > 0 and,
** if so, closes the specified file. Otherwise it does nothing.
** IF refNum were > 0, it would call CloseResFile(refNum)
** which does NOT pertain to a Movie file. This is why we
** canNOT just call CResFile::Close and be done. */
// inherited::Close();
} /* Close */
// OVERRIDE
void CMovieFile::ThrowOut (void) {
FSSpec movieSpec;
Close();
;
GetFSSpec(&movieSpec);
FailOSErr( DeleteMovieFile(&movieSpec) );
} /* ThrowOut */
// OVERRIDE
void CMovieFile::ChangeName (Str63 newName) {
FSSpec movieSpec;
GetFSSpec(&movieSpec);
FailOSErr( FSpRename(&movieSpec, newName) );
;
CopyPString(newName, name);
} /* ChangeName */
// OVERRIDE
void CMovieFile::Update (void) {
Boolean wasLocked;
OSErr err;
Movie localMoov = theMovie->GetMovie();
FSSpec theSpec;
short rsrcID = 0; // Assign new unique ID;
ASSERT( IsOpen() );
wasLocked = Lock(TRUE);
;
if ( HasMovieChanged(localMoov) )
{
err = UpdateMovieResource(localMoov, refNum, resID, name);
if (err != noErr)
{
Lock(wasLocked);
FailOSErr(err);
}
GetFSSpec(&theSpec);
FlattenMovie(
localMoov,
flattenAddMovieToDataFork,
&theSpec,
gSignature,
iuSystemScript,
createMovieFileDeleteCurFile,
&rsrcID,
theSpec.name
);
err = GetMoviesError();
if (err != noErr)
{
Lock(wasLocked);
FailOSErr(err);
}
resID = rsrcID;
}
else
{
err = FlushVol("", volNum);
}
;
Lock(wasLocked);
FailOSErr(err);
} /* Update */
// OVERRIDE
void CMovieFile::ResolveFileAlias (void) {
/* Resolve the current File specification in case it is an alias.
** Although the Finder and Standard File packages resolve aliases
** for you, calling this method may be necessary if you open a file
** directly. CFile's Specify methods call ResolveFileAlias for you. */
OSErr err;
FSSpec fileSpec;
AliasHandle alias;
Boolean isFolder, wasAliased, wasChanged;
GetFSSpec(&fileSpec);
if (gSystem.hasAliasMgr) /* System 7 */ {
err = ResolveAliasFile(&fileSpec, true, &isFolder, &wasAliased);
;
if (err == fnfErr) {
/* ????? */
}
else if (err != noErr) {
Failure (err, 0);
}
else /* NO error */ {
if (wasAliased) /* copy back alias' specification */ {
CopyPString(fileSpec.name, name);
dirID = fileSpec.parID;
volNum = fileSpec.vRefNum;
}
// Raise exception if this is a directory since we handle only files:
if (isFolder) Failure(paramErr, 0);
}
} /* System 7 */
else if ( /* System 6 and */ QuickTimeIsInstalled() ) {
// QuickTime has limited Alias Manager support for System 6:
err = NewAlias(nil /* e.g., does not support relative path info */,
&fileSpec, &alias);
;
if (alias != NULL) {
err = ResolveAlias(nil /* does not support relative path info */,
alias, &fileSpec /* target */, &wasChanged);
;
if (err == fnfErr) {
/* ????? */
}
else if (err != noErr) {
Failure (err, 0);
}
else /* NO error, so copy back info */ {
CopyPString(fileSpec.name, name);
dirID = fileSpec.parID;
volNum = fileSpec.vRefNum;
}
} /* alias != NULL */
} /* System 6 && QuickTime */
} /* ResolveFileAlias */
void CMovie::MakeMovieEditTask (long theCommand) {
CMovieEditTask *newEditTask = NULL;
TRY
{
newEditTask = new (CMovieEditTask);
newEditTask->IMovieEditTask(this, theCommand, cFirstMovieEditTaskIndex);
}
CATCH
{
ForgetObject(newEditTask);
}
ENDTRY;
lastMovieEditTask = newEditTask;
} /* MakeMovieEditTask */
void CMovieEditTask::IMovieEditTask (CMovie *thisMoviePane, long theCommand,
short firstTaskIndex) {
// Moving memory:
Movie activeMoov, localMoov, localScrap;
MovieController activeMC;
TimeValue start = 0, movieLength, inputTime, inputDuration;
OSErr err;
short taskIndex;
// Fill in some instance variables:
if (theCommand == cmdRevert || theCommand == cmdPaste) {
activeMoov = thisMoviePane->GetMovie();
activeMC = thisMoviePane->GetController();
;
movieLength = GetMovieDuration(activeMoov);
FailOSErr( GetMoviesError() );
if (movieLength > 0) {
GetMovieSelection(activeMoov, &inputTime, &inputDuration);
FailOSErr( GetMoviesError() );
SetMovieSelection(activeMoov, start, movieLength);
FailOSErr( GetMoviesError() );
;
localMoov = MCCopy(activeMC);
FailOSErr( GetMoviesError() );
;
SetMovieSelection(activeMoov, inputTime, inputDuration);
FailOSErr( GetMoviesError() );
}
else
localMoov = NewMovie(newMovieActive);
;
originalMoov = localMoov;
}
else
originalMoov = NULL;
if (theCommand == cmdCut || theCommand == cmdCopy) {
/* pasting and clearing do NOT affect the scrap */
localScrap = NewMovieFromScrap(newMovieActive);
err = GetMoviesError();
if (err == noMoovOnScrap) {
/* QuickTime 1.0 returned a nil Movie with
** a err = noErr if zip in the Scrap. NO mo!! */
err = noErr;
localScrap = NULL;
}
FailOSErr(err);
originalScrap = localScrap;
}
else
originalScrap = NULL;
editedMoviePane = thisMoviePane;
editCmd = theCommand;
if (firstTaskIndex > 0)
{
if (theCommand == cmdRevert)
taskIndex = firstTaskIndex;
else
taskIndex = firstTaskIndex + theCommand - cmdCut + 1;
}
else taskIndex = 0; /* This indicates we did NOT supply any
** strings at all in which case the Undo
** item will ALWAYS read just "Undo". */
inherited::ITask(taskIndex);
} /* IMovieEditTask */
// OVERRIDE
void CMovieEditTask::Do (void) {
Movie activeMoov, localMoov, localScrap;
MovieController activeMC;
TimeValue start = 0, movieLength, inputTime, inputDuration;
CMovie *thisMoviePane = editedMoviePane;
OSErr err;
// Fill in remaining instance variables:
if (editCmd == cmdRevert || editCmd == cmdPaste) {
activeMoov = thisMoviePane->GetMovie();
activeMC = thisMoviePane->GetController();
;
movieLength = GetMovieDuration(activeMoov);
FailOSErr( GetMoviesError() );
if (movieLength > 0) {
GetMovieSelection(activeMoov, &inputTime, &inputDuration);
FailOSErr( GetMoviesError() );
SetMovieSelection(activeMoov, start, movieLength);
FailOSErr( GetMoviesError() );
;
localMoov = MCCopy(activeMC);
FailOSErr( GetMoviesError() );
;
SetMovieSelection(activeMoov, inputTime, inputDuration);
FailOSErr( GetMoviesError() );
}
else
localMoov = NewMovie(newMovieActive);
;
newMoov = localMoov;
}
else
newMoov = NULL;
if (editCmd == cmdCut || editCmd == cmdCopy) {
/* pasting and clearing do NOT affect the scrap */
localScrap = NewMovieFromScrap(newMovieActive);
err = GetMoviesError();
if (err == noMoovOnScrap) {
err = noErr;
localScrap = NULL;
}
FailOSErr(err);
newScrap = localScrap;
}
else
newScrap = NULL;
// inherited::Do(); -- EMPTY !!!
} /* Do */
// OVERRIDE
void CMovieEditTask::Undo (void) {
CQuickTime *myDoc;
OSErr err;
Movie saveOriginalScrap, saveNewScrap, localScrap,
undoneMoov,
activeMoov = editedMoviePane->GetMovie();
MovieController activeMC = editedMoviePane->GetController();
TimeValue noDuration = 0, movieLength, currentTime;
CWindow *theWindow = editedMoviePane->GetWindow();
GrafPtr localPort = editedMoviePane->GetMacPort();
long zeroFlags = 0;
saveOriginalScrap = originalScrap;
saveNewScrap = newScrap;
switch (editCmd) {
case cmdCut:
// theWindow->HideSuspend(); -- was NOT hidden when originally cut.
;
MCUndo(activeMC);
FailOSErr( GetMoviesError() );
;
// theWindow->ShowResume();
break; /* cmdCut */
case cmdCopy:
/* Just need to swap out the scrap which
** we do following the switch-statement. */
break; /* cmdCopy */
case cmdRevert:
/* Do the same as cmdPaste, with two immediate additions
** and some selection changes noted below: */
myDoc = (CQuickTime*) editedMoviePane->GetSupervisor();
myDoc->dirty = !undone;
justSaved = true; // For my special CView::DispatchCursor.
case cmdPaste:
/* Weird things happen when UNdoing a paste operation
** wherein you pressed the <Shift> key to paste over an
** existing selection, whether said selection consists
** of several contiguous frames or the entire Movie.
** In these cases, UNdoing using MCUndo does not revert
** to what was there originally. This is because I call
** MCClear on the existing selection before I paste. */
theWindow->HideSuspend();
;
movieLength = GetMovieDuration(activeMoov);
FailOSErr( GetMoviesError() );
if (movieLength > 0) {
SetMovieSelection(activeMoov, 0 /* at beginning */, movieLength);
FailOSErr( GetMoviesError() );
MCClear(activeMC);
FailOSErr( GetMoviesError() );
}
if ( !undone ) /* Undo */ undoneMoov = originalMoov;
else /* Redo */ undoneMoov = newMoov;
movieLength = GetMovieDuration(undoneMoov);
FailOSErr( GetMoviesError() );
if (movieLength > 0) {
SetMovieSelection(undoneMoov, 0, movieLength);
FailOSErr( GetMoviesError() );
MCPaste(activeMC, undoneMoov);
FailOSErr( GetMoviesError() );
if (editCmd == cmdRevert) {
SetMovieSelection(activeMoov, 0, noDuration); // Zip.
FailOSErr( GetMoviesError() );
GoToBeginningOfMovie(activeMoov);
FailOSErr( GetMoviesError() );
}
else /* cmdPaste */ {
currentTime = GetMovieTime(activeMoov, nil);
FailOSErr( GetMoviesError() );
SetMovieSelection(activeMoov, currentTime, noDuration);
FailOSErr( GetMoviesError() );
editedMoviePane->Activate();
}
}
;
theWindow->ShowResume();
break; /* cmdRevert & cmdPaste */
case cmdClear:
/*
** Doesn't look bad at all even though we hid
** the window when clearing the entire Movie:
theWindow->HideSuspend();
*/
MCUndo(activeMC);
FailOSErr( GetMoviesError() );
// theWindow->ShowResume();
break; /* cmdClear */
} /* end: switch */
if ( (editCmd == cmdCut) || (editCmd == cmdCopy) ) {
/*
** Only these Commands affect the Scrap.
**
** MCUndo does NOT swap out the Scrap. Specifically,
** MCUndo keeps the Scrap contents = newScrap:
*/
if ( !undone ) /* Undo */ {
if (originalScrap != NULL) {
/* PutMovieOnScrap places a copy on the Scrap,
** so we must dispose of the ORIGINAL original: */
localScrap = originalScrap;
FailOSErr( PutMovieOnScrap(localScrap, zeroFlags) );
DisposeMovie(originalScrap);
FailOSErr( GetMoviesError() );
}
else FailOSErr( ZeroScrap() );
;
localScrap = NewMovieFromScrap(newMovieActive);
err = GetMoviesError();
if (err == noMoovOnScrap) {
err = noErr;
localScrap = NULL;
}
FailOSErr(err);
originalScrap = localScrap;
newScrap = saveNewScrap;
}
else /* Redo */ {
// For cutting & copying, the newScrap is always != NULL:
// if (newScrap != NULL) {
localScrap = newScrap;
FailOSErr( PutMovieOnScrap(localScrap, zeroFlags) );
DisposeMovie(newScrap); // New copy now on Scrap.
FailOSErr( GetMoviesError() );
// }
// else FailOSErr( ZeroScrap() );
;
localScrap = NewMovieFromScrap(newMovieActive);
err = GetMoviesError();
if (err == noMoovOnScrap) {
err = noErr;
localScrap = NULL;
}
FailOSErr(err);
newScrap = localScrap;
originalScrap = saveOriginalScrap;
}
} /* cut or copy */
inherited::Undo(); /* Toggles CTask::undone */
} /* Undo */
// OVERRIDE
void CMovieEditTask::Dispose (void) {
if (originalMoov != NULL && GetMovieDuration(originalMoov) > 0) {
DisposeMovie(originalMoov);
FailOSErr( GetMoviesError() );
originalMoov = NULL;
}
if (newMoov != NULL && GetMovieDuration(newMoov) > 0) {
DisposeMovie(newMoov);
FailOSErr( GetMoviesError() );
newMoov = NULL;
}
if (originalScrap != NULL) {
DisposeMovie(originalScrap);
FailOSErr( GetMoviesError() );
originalScrap = NULL;
}
if (newScrap != NULL) {
DisposeMovie(newScrap);
FailOSErr( GetMoviesError() );
newScrap = NULL;
}
inherited::Dispose();
} /* Dispose */
CIconHandle CRemoteIconPane::GetCICN (void) {
/* So I can access the protected variable */
return (cicnH);
} /* GetCICN */
void CRemoteIconPane::SetCICN (CIconHandle theCICN) {
/* So I can set the protected variable */
cicnH = theCICN;
} /* SetCICN */
// OVERRIDE
void CRemoteIconPane::DoClick (Point hitPt, short modifierKeys, long when) {
CRemote *theDoc;
CRemoteNullClickPane *dimLit; // Nothing personal, fella !!
CIconHandle lightOff;
/* FindViewByID must start at the top to work,
** so begin with the CDocument supervisor: */
theDoc = (CRemote*) GetSupervisor();
dimLit = (CRemoteNullClickPane*) theDoc->FindViewByID('lite');
if (dimLit != NULL)
{
ForceNextPrepare();
dimLit->Prepare();
;
lightOff = dimLit->GetCICN();
LoadResource(lightOn);
dimLit->SetCICN(lightOn);
dimLit->DrawIcon(FALSE); // Turn light "on".
;
ForceNextPrepare();
/* this-> */Prepare();
}
if (Track())
{
itsSupervisor->DoCommand( GetClickCmd() );
}
if (dimLit != NULL)
{
ForceNextPrepare();
dimLit->Prepare();
;
dimLit->SetCICN(lightOff);
dimLit->DrawIcon(FALSE); // Turn "off".
;
ForceNextPrepare();
/* this-> */Prepare();
}
} /* DoClick */
// OVERRIDE
Boolean CRemoteScrollPane::Track (void) {
/* Continuously execute the clickCmd while
** mouse is down inside the icon frame: */
Boolean inBtn = TRUE;
Point where;
Rect qdFrame;
GrafPtr scrollIconPort = macPort;
DrawIcon(TRUE);
FrameToQDR(&frame, &qdFrame);
while ( StillDown() )
{
GetMouse(&where);
;
if (PtInRect(where, &qdFrame))
{
if (!inBtn) DrawIcon(TRUE);
inBtn = TRUE;
}
else
{
if (inBtn) DrawIcon(FALSE);
inBtn = FALSE;
}
if (inBtn)
{
itsSupervisor->DoCommand( GetClickCmd() );
// DoCommand above calls CQuickTime::itsMovie->Prepare().
ForceNextPrepare();
Prepare();
}
}
if (inBtn)
{
ForceNextPrepare();
Prepare();
DrawIcon(FALSE);
}
// So CIconPane::DoClick does not execute the clickCmd AGAIN:
return (FALSE);
} /* Track */
// OVERRIDE
void CRemoteNullClickPane::DoClick (Point hitPt, short modifierKeys, long when) {
// Do zip !!!
} /* DoClick */
void CRemote::IRemote (CApplication *itsSupervisor) {
#define kRemoteHelp 5000
Boolean savedAlloc;
CWindow *smartWindow = NULL;
Rect smartRect = {0, 0, 350, 150};
short hPos, vPos;
CRemoteMainPane *mainRemotePane;
CRemoteNullClickPane *light;
CIconPane /* *light, */ *eject, *load, *power, // by row:
*pause, *stop,
*playBackward, *playForward,
*goToStart, /* *stepBackward, *stepForward, */ *goToEnd,
/* *volDown, *volUp, */
*logo;
CRemoteScrollPane *stepBackward, *stepForward,
*volDown, *volUp;
inherited::IDocument(itsSupervisor, false /* NOT printable */);
smartWindow = new (CWindow);
itsWindow = smartWindow;
itsWindow->INewWindow(&smartRect, false /* NOT visible */,
rDocProc, true /* floating */,
false /* NO goAway box */,
(CFWDesktop*) gDesktop, this);
;
/* CWindow::IWindowX sets minimum window size =
** CWindow::sizeRect.topLeft = {100, 100} */
itsWindow->sizeRect.top = smartRect.top;
itsWindow->sizeRect.left = smartRect.left;
;
itsWindow->SetTitle("\pRemote Control");
;
itsWindow->SetHelpResID(kRemoteHelp);
// The Main man ...
mainRemotePane = new (CRemoteMainPane);
mainRemotePane->IPane(
itsWindow,
this,
0, 0, 0, 0,
sizELASTIC, sizELASTIC
);
mainRemotePane->FitToEnclosure(true, true);
mainRemotePane->SetWantsClicks(TRUE); // So the sub-Views see clicks.
mainRemotePane->helpResIndex = 15;
itsMainPane = mainRemotePane;
// Next, turn on the lights:
savedAlloc = SetAllocation(kAllocCanFail);
lightOn = GetCIcon(kLightLight);
SetAllocation(savedAlloc);
FailNIL(lightOn);
HPurge(lightOn);
/* 1 */
light = new (CRemoteNullClickPane);
light->IIconPane(
mainRemotePane,
this,
5, 18,
sizFIXEDSTICKY, sizFIXEDSTICKY,
kDimLight, /* cicn ID */
true /* fPreferColor */
);
light->SetWantsClicks(TRUE); // See comments within "CQuickTime.h"
light->helpResIndex = 1;
light->SetID('lite');
// Now for the remaining zillion sub-Views:
/* 2 */
eject = new (CRemoteIconPane);
eject->IIconPane(
mainRemotePane,
this,
41, 18,
sizFIXEDSTICKY, sizFIXEDSTICKY,
kEject, /* cicn ID */
true /* fPreferColor */
);
eject->SetWantsClicks(TRUE);
eject->SetClickCmd(kEject);
eject->helpResIndex = 2;
/* 3 */
load = new (CRemoteIconPane);
load->IIconPane(
mainRemotePane,
this,
77, 18,
sizFIXEDSTICKY, sizFIXEDSTICKY,
kLoad, true
);
load->SetWantsClicks(TRUE);
load->SetClickCmd(kLoad);
load->helpResIndex = 3;
/* 4 */
power = new (CRemoteIconPane);
power->IIconPane(
mainRemotePane,
this,
113, 18,
sizFIXEDSTICKY, sizFIXEDSTICKY,
kPower, true
);
power->SetWantsClicks(TRUE);
power->SetClickCmd(kPower);
power->helpResIndex = 4;
/* 5 */
pause = new (CRemoteIconPane);
pause->IIconPane(
mainRemotePane,
this,
33, 80,
sizFIXEDSTICKY, sizFIXEDSTICKY,
kPause, true
);
pause->SetWantsClicks(TRUE);
pause->SetClickCmd(kPause);
pause->helpResIndex = 5;
/* 6 */
stop = new (CRemoteIconPane);
stop->IIconPane(
mainRemotePane,
this,
85, 80,
sizFIXEDSTICKY, sizFIXEDSTICKY,
kStop, true
);
stop->SetWantsClicks(TRUE);
stop->SetClickCmd(kStop);
stop->helpResIndex = 6;
/* 7 */
playBackward = new (CRemoteIconPane);
playBackward->IIconPane(
mainRemotePane,
this,
33, 132,
sizFIXEDSTICKY, sizFIXEDSTICKY,
kPlayBackward, true
);
playBackward->SetWantsClicks(TRUE);
playBackward->SetClickCmd(kPlayBackward);
playBackward->helpResIndex = 7;
/* 8 */
playForward = new (CRemoteIconPane);
playForward->IIconPane(
mainRemotePane,
this,
85, 132,
sizFIXEDSTICKY, sizFIXEDSTICKY,
kPlayForward, true
);
playForward->SetWantsClicks(TRUE);
playForward->SetClickCmd(kPlayForward);
playForward->helpResIndex = 8;
/* 9 */
goToStart = new (CRemoteIconPane);
goToStart->IIconPane(
mainRemotePane,
this,
5, 184,
sizFIXEDSTICKY, sizFIXEDSTICKY,
kGoToStart, true
);
goToStart->SetWantsClicks(TRUE);
goToStart->SetClickCmd(kGoToStart);
goToStart->helpResIndex = 9;
/* 10 */
stepBackward = new (CRemoteScrollPane);
stepBackward->IIconPane(
mainRemotePane,
this,
41, 184,
sizFIXEDSTICKY, sizFIXEDSTICKY,
kStepBackward, true
);
stepBackward->SetWantsClicks(TRUE);
stepBackward->SetClickCmd(kStepBackward);
stepBackward->helpResIndex = 10;
/* 11 */
stepForward = new (CRemoteScrollPane);
stepForward->IIconPane(
mainRemotePane,
this,
77, 184,
sizFIXEDSTICKY, sizFIXEDSTICKY,
kStepForward, true
);
stepForward->SetWantsClicks(TRUE);
stepForward->SetClickCmd(kStepForward);
stepForward->helpResIndex = 11;
/* 12 */
goToEnd = new (CRemoteIconPane);
goToEnd->IIconPane(
mainRemotePane,
this,
113, 184,
sizFIXEDSTICKY, sizFIXEDSTICKY,
kGoToEnd, true
);
goToEnd->SetWantsClicks(TRUE);
goToEnd->SetClickCmd(kGoToEnd);
goToEnd->helpResIndex = 12;
/* 13 */
volDown = new (CRemoteScrollPane);
volDown->IIconPane(
mainRemotePane,
this,
33, 236,
sizFIXEDSTICKY, sizFIXEDSTICKY,
kVolumeDown, true
);
volDown->SetWantsClicks(TRUE);
volDown->SetClickCmd(kVolumeDown);
volDown->helpResIndex = 13;
/* 14 */
volUp = new (CRemoteScrollPane);
volUp->IIconPane(
mainRemotePane,
this,
85, 236,
sizFIXEDSTICKY, sizFIXEDSTICKY,
kVolumeUp, true
);
volUp->SetWantsClicks(TRUE);
volUp->SetClickCmd(kVolumeUp);
volUp->helpResIndex = 14;
/* 15 */
logo = new (CRemoteIconPane);
logo->IIconPane(
mainRemotePane,
this,
59, 288,
sizFIXEDSTICKY, sizFIXEDSTICKY,
kLogo, true
);
/* default state when IPane is eventually called:
**
** logo->SetWantsClicks(FALSE);
** logo->helpResIndex = 0;
*/
/* Place this contraption off to the side somewhere because
** when we open up existing Movies or create empty ones,
** we'll be centering the Movie. */
hPos = screenBits.bounds.right - 150 - 20 /* arbitrary offset */;
vPos = GetMBarHeight() + 18 /* window's drag bar */ + 20 /* offset */;
itsWindow->Move(hPos, vPos);
} /* IRemote */
void CRemote::Dispose (void) {
LoadResource(lightOn); // May have been purged.
DisposCIcon(lightOn);
inherited::Dispose();
} /* Dispose */
// OVERRIDE
void CRemoteMainPane::Draw (Rect *area) {
CWindow *myWindow;
PenState pnState;
short saveTextMode, saveTextFont, saveTextSize;
LongRect remoteRect;
Rect remoteR, roundR;
GetPenState(&pnState);
saveTextMode = macPort->txMode;
saveTextFont = macPort->txFont;
saveTextSize = macPort->txSize;
;
myWindow = GetWindow();
myWindow->GetInterior(&remoteRect);
LongToQDRect(&remoteRect, &remoteR);
EraseRect(&remoteR);
roundR = remoteR;
InsetRect(&roundR, 1, 1);
PenSize(2, 2);
FrameRoundRect(&roundR, 16, 16);
InvertRect(&remoteR); // Black background.
PenNormal();
PenMode(notPatCopy); // Draw white on black ...
TextMode(notSrcCopy);
TextFont(geneva);
TextSize(9);
// Draw the names of the various "Buttons":
MoveTo(remoteR.left + 116, remoteR.top + 14);
DrawString("\pPower");
;
MoveTo(remoteR.left + 37, remoteR.top + 76);
DrawString("\ppause");
;
MoveTo(remoteR.left + 92, remoteR.top + 76);
DrawString("\pstop");
;
MoveTo(remoteR.left + 35, remoteR.top + 128);
DrawString("\pplay B");
;
MoveTo(remoteR.left + 87, remoteR.top + 128);
DrawString("\pplay F");
;
MoveTo(remoteR.left + 9, remoteR.top + 180);
DrawString("\pstart");
;
MoveTo(remoteR.left + 43, remoteR.top + 180);
DrawString("\pstep B");
;
MoveTo(remoteR.left + 79, remoteR.top + 180);
DrawString("\pstep F");
;
MoveTo(remoteR.left + 121, remoteR.top + 180);
DrawString("\pend");
;
MoveTo(remoteR.left + 40, remoteR.top + 233);
DrawString("\pvol-");
;
MoveTo(remoteR.left + 92, remoteR.top + 233);
DrawString("\pvol+");
// Finally, draw the title at the bottom:
MoveTo(remoteR.left + 20, remoteR.top + 340);
DrawString("\pQuickTime Smart Remote");
;
TextMode(saveTextMode);
TextFont(saveTextFont);
TextSize(saveTextSize);
SetPenState(&pnState);
} /* CRemoteMainPane::Draw */
// OVERRIDE
void CRemoteMainPane::ShowHelpBalloon (struct HMMessageRecord *helpData, Point tip,
RectPtr altRect, Ptr tipProc, short theProc,
short variant, short method) {
/* All this just to reposition the Balloon tip for the main CPane of the
** remote control window. Otherwise, the TCL will simply place the tip
** at the center of the passed "altRect". Normally, this is just fine;
** however, in this case I felt that the Balloons looked too busy as you
** moved the Mouse from pane to pane ... dealer's choice. */
OSErr err;
Boolean savedAlloc;
cCurrHelpView = this;
if ( (cLastHelpView != this) && (helpData->hmmHelpType != 0) )
{
savedAlloc = SetAllocation(kAllocCanFail);
SetPt(&tip, altRect->left + 65, altRect->bottom - 15);
err = HMShowBalloon(helpData, tip, altRect, tipProc,
theProc, variant, method);
SetAllocation(savedAlloc);
if (err)
{
cCurrHelpView = NULL;
if (err != hmBalloonAborted) Failure(err, 0);
}
}
} /* ShowHelpBalloon */
// OVERRIDE
void CRemote::DoCommand (long theCommand) {
#define kNoSoundInMovie 255
/* gotta subtract at least 2 or otherwise cross thread with no sound value: */
#define kBlasting kFullVolume /* = 256 */ - 2
Movie localMoov;
MovieController localMC;
TimeValue lengthMovie, currentTime;
Fixed playRate;
short volume;
CWindow *front = ((CFWDesktop*) gDesktop)->topWindow;
Boolean noMovie = (front == nil) ||
(gClipboard->windowVisible);
switch (theCommand) {
case kEject: // Pane #1
if (noMovie) SysBeep(10);
else ( (CMovie*) gGopher )->DoCommand(cmdClose);
break; /* kEject */
case kLoad: // Pane #2
gApplication->DoCommand(cmdOpen);
break; /* kLoad */
case kPower: // Pane #3
gApplication->DoCommand(cmdQuit);
break; /* kPower */
case kPause: // Pane #4
if (noMovie) SysBeep(10);
else
{ TimeValue initialTime, delayTime;
( (CMovie*) gGopher )->Prepare();
localMoov = ( (CMovie*) gGopher )->GetMovie();
localMC = ( (CMovie*) gGopher )->GetController();
MCDoAction(localMC, mcActionGetPlayRate, &playRate);
;
if (playRate != 0)
{
initialTime = GetMovieTime(localMoov, nil);
FailOSErr( GetMoviesError() );
MoviesTask(localMoov, 1);
delayTime = GetMovieTime(localMoov, nil);
FailOSErr( GetMoviesError() );
if ( Abs(delayTime - initialTime) > 0 )
{ // Does NOT change Pause button to Play button:
StopMovie(localMoov);
FailOSErr( GetMoviesError() );
}
else SysBeep(10);
}
else
SysBeep(10);
} /* have a Movie window */
break; /* kPause */
case kStop: // Pane #5
if (noMovie) SysBeep(10);
else
{
( (CMovie*) gGopher )->Prepare();
localMC = ( (CMovie*) gGopher )->GetController();
MCDoAction(localMC, mcActionGetPlayRate, &playRate);
;
if (playRate != 0)
{ /* Call this, not StopMovie, to change the Pause button
** back to the Play button on the Movie Controller bar: */
MCDoAction(localMC, mcActionPlay, (void*) 0);
}
else
SysBeep(10);
} /* have a Movie window */
break; /* kStop */
case kPlayBackward: // Pane #6
if (noMovie) SysBeep(10);
else
{
localMoov = ( (CMovie*) gGopher )->GetMovie();
lengthMovie = GetMovieDuration(localMoov);
FailOSErr( GetMoviesError() );
if (lengthMovie == 0)
SysBeep(10);
else
( (CMovie*) gGopher )->DoCommand(cmdPlayBackward);
} /* have a Movie window */
break; /* kPlayBackward */
case kPlayForward: // Pane #7
if (noMovie) SysBeep(10);
else
{
localMoov = ( (CMovie*) gGopher )->GetMovie();
lengthMovie = GetMovieDuration(localMoov);
FailOSErr( GetMoviesError() );
if (lengthMovie == 0)
SysBeep(10);
else
( (CMovie*) gGopher )->DoCommand(cmdPlayForward);
} /* have a Movie window */
break; /* kPlayForward */
case kGoToStart: // Pane #8
if (noMovie) SysBeep(10);
else
{
localMoov = ( (CMovie*) gGopher )->GetMovie();
currentTime = GetMovieTime(localMoov, nil);
FailOSErr( GetMoviesError() );
if (currentTime == 0)
SysBeep(10);
else
( (CMovie*) gGopher )->DoCommand(cmdGoToBeginning);
} /* have a Movie window */
break; /* kGoToStart */
case kStepBackward: // Pane #9
if (noMovie) SysBeep(10);
else
{
localMC = ( (CMovie*) gGopher )->GetController();
localMoov = ( (CMovie*) gGopher )->GetMovie();
lengthMovie = GetMovieDuration(localMoov);
FailOSErr( GetMoviesError() );
if (lengthMovie > 0)
{
( (CMovie*) gGopher )->Prepare();
/*
** CIconScrollPane takes care of tracking the mouse
while ( StillDown() )
{
*/
currentTime = GetMovieTime(localMoov, nil);
FailOSErr( GetMoviesError() );
if (currentTime == 0)
{
SysBeep(10);
break;
}
else
{
MCDoAction(localMC, mcActionStep, (void*) ((Fixed) -1));
MCIdle(localMC);
}
// } /* while */
} /* lengthMovie > 0 */
else SysBeep(10);
} /* have a Movie window */
break; /* kStepBackward */
case kStepForward: // Pane #10
if (noMovie) SysBeep(10);
else
{
localMC = ( (CMovie*) gGopher )->GetController();
localMoov = ( (CMovie*) gGopher )->GetMovie();
lengthMovie = GetMovieDuration(localMoov);
FailOSErr( GetMoviesError() );
if (lengthMovie > 0)
{
( (CMovie*) gGopher )->Prepare();
/*
** CIconScrollPane takes care of tracking the mouse
while ( StillDown() )
{
*/
currentTime = GetMovieTime(localMoov, nil);
FailOSErr( GetMoviesError() );
if (currentTime == lengthMovie)
{
SysBeep(10);
break;
}
else
{
MCDoAction(localMC, mcActionStep, (void*) ((Fixed) 1));
MCIdle(localMC);
}
// } /* while */
} /* lengthMovie > 0 */
else SysBeep(10);
} /* have a Movie window */
break; /* kStepForward */
case kGoToEnd: // Pane #11
if (noMovie) SysBeep(10);
else
{
localMoov = ( (CMovie*) gGopher )->GetMovie();
currentTime = GetMovieTime(localMoov, nil);
FailOSErr( GetMoviesError() );
lengthMovie = GetMovieDuration(localMoov);
FailOSErr( GetMoviesError() );
if (currentTime == lengthMovie)
SysBeep(10);
else
( (CMovie*) gGopher )->DoCommand(cmdGoToEnd);
} /* have a Movie window */
break; /* kGoToEnd */
case kVolumeDown: // Pane #12
if (noMovie) SysBeep(10);
else
{
( (CMovie*) gGopher )->Prepare();
localMoov = ( (CMovie*) gGopher )->GetMovie();
/*
** CIconScrollPane takes care of tracking the mouse
while ( StillDown() )
{
*/
volume = GetMovieVolume(localMoov);
FailOSErr ( GetMoviesError() );
if (volume == kNoSoundInMovie || volume == kNoVolume)
{
SysBeep(10);
}
else
{
volume--;
if (volume < kNoVolume) volume = kNoVolume;
SetMovieVolume(localMoov, volume);
FailOSErr ( GetMoviesError() );
MCIdle(localMC);
}
// } /* while */
} /* have a Movie window */
break; /* kVolumeDown */
case kVolumeUp: // Pane #13
if (noMovie) SysBeep(10);
else
{
( (CMovie*) gGopher )->Prepare();
localMoov = ( (CMovie*) gGopher )->GetMovie();
/*
** CIconScrollPane takes care of tracking the mouse
while ( StillDown() )
{
*/
volume = GetMovieVolume(localMoov);
FailOSErr ( GetMoviesError() );
if (volume == kNoSoundInMovie || volume == kBlasting)
{
SysBeep(10);
}
else
{
volume++;
if (volume > kBlasting) volume = kBlasting;
SetMovieVolume(localMoov, volume);
FailOSErr ( GetMoviesError() );
MCIdle(localMC);
}
// } /* while */
} /* have a Movie window */
break; /* kVolumeUp */
default:
inherited::DoCommand(theCommand);
break;
} /* end: switch */
} /* CRemote::DoCommand */
// Save the NON-Class routines until last:
Boolean QuickTimeIsInstalled (void) {
/* Do we have a machine on which QuickTime is installed ??? */
long myFeature;
return (TrapAvailable(_GestaltDispatch) &&
Gestalt(gestaltQuickTime, &myFeature) == noErr);
} /* QuickTimeIsInstalled */
void ConvertOldToNew (SFReply *oldSF, StandardFileReply *newSF) {
/* Convert an old style SFReply into a System 7 StandardFileReply. */
OSErr err;
newSF->sfGood = oldSF->good;
newSF->sfReplacing = oldSF->copy;
newSF->sfType = oldSF->fType;
err = FSMakeFSSpec(oldSF->vRefNum, specifiedByRefNumAndFileName,
oldSF->fName, &newSF->sfFile);
if (err == fnfErr) err = noErr; // FSSpec still valid.
FailOSErr(err);
newSF->sfScript = iuSystemScript;
newSF->sfFlags = 0;
newSF->sfIsFolder = false;
newSF->sfIsVolume = false;
newSF->sfReserved1 = 0;
newSF->sfReserved2 = 0;
} /* ConvertOldToNew */
/* { end file "CQuickTime.c" } */